From cafcee3d86159c23cf0c86a0420072556d433c7f Mon Sep 17 00:00:00 2001 From: Gabriel Russell Date: Thu, 17 Mar 2016 13:21:14 -0400 Subject: TOOLS-1100 revendor spacemonkeygo/openssl --- Godeps | 2 +- .../src/github.com/spacemonkeygo/openssl/cert.go | 32 +++- .../github.com/spacemonkeygo/openssl/cert_test.go | 44 +++++- .../src/github.com/spacemonkeygo/openssl/conn.go | 90 ++++++++--- vendor/src/github.com/spacemonkeygo/openssl/ctx.go | 80 +++++++++- .../github.com/spacemonkeygo/openssl/ctx_test.go | 48 ++++++ .../src/github.com/spacemonkeygo/openssl/digest.go | 53 +++++++ vendor/src/github.com/spacemonkeygo/openssl/key.go | 37 +++++ vendor/src/github.com/spacemonkeygo/openssl/net.go | 19 +++ .../spacemonkeygo/openssl/old_openssl_compat.go | 44 ------ vendor/src/github.com/spacemonkeygo/openssl/sni.c | 23 +++ .../github.com/spacemonkeygo/openssl/sni_test.go | 23 +++ vendor/src/github.com/spacemonkeygo/openssl/ssl.go | 167 +++++++++++++++++++++ .../src/github.com/spacemonkeygo/openssl/verify.c | 10 +- 14 files changed, 594 insertions(+), 78 deletions(-) create mode 100644 vendor/src/github.com/spacemonkeygo/openssl/ctx_test.go create mode 100644 vendor/src/github.com/spacemonkeygo/openssl/digest.go delete mode 100644 vendor/src/github.com/spacemonkeygo/openssl/old_openssl_compat.go create mode 100644 vendor/src/github.com/spacemonkeygo/openssl/sni.c create mode 100644 vendor/src/github.com/spacemonkeygo/openssl/sni_test.go create mode 100644 vendor/src/github.com/spacemonkeygo/openssl/ssl.go diff --git a/Godeps b/Godeps index 62a028595db..f37c9680ec2 100644 --- a/Godeps +++ b/Godeps @@ -6,6 +6,6 @@ github.com/smartystreets/assertions 287b4346dc4e71a038c346375a9d572453bc469b github.com/smartystreets/goconvey bf58a9a1291224109919756b4dcc469c670cc7e4 github.com/jessevdk/go-flags 97448c91aac742cbca3d020b3e769013a420a06f github.com/3rf/mongo-lint 3550fdcf1f43b89aaeabaa4559eaae6dc4407e42 -github.com/spacemonkeygo/openssl 4c6dbafa5ec35b3ffc6a1b1e1fe29c3eba2053ec github.com/10gen/openssl +github.com/spacemonkeygo/openssl 28e108cf76dcb7bd5aa445a0f4348b312464004e github.com/10gen/openssl github.com/howeyc/gopass 44476384cd4721b68705e72f19e95d1a3a504370 golang.org/x/crypto 1f22c0103821b9390939b6776727195525381532 diff --git a/vendor/src/github.com/spacemonkeygo/openssl/cert.go b/vendor/src/github.com/spacemonkeygo/openssl/cert.go index 673da8574bb..61637c649fa 100644 --- a/vendor/src/github.com/spacemonkeygo/openssl/cert.go +++ b/vendor/src/github.com/spacemonkeygo/openssl/cert.go @@ -27,6 +27,7 @@ import "C" import ( "errors" "io/ioutil" + "math/big" "runtime" "time" "unsafe" @@ -57,7 +58,7 @@ type Certificate struct { } type CertificateInfo struct { - Serial int + Serial *big.Int Issued time.Duration Expires time.Duration Country string @@ -106,6 +107,19 @@ func (n *Name) AddTextEntries(entries map[string]string) error { return nil } +// GetEntry returns a name entry based on NID. If no entry, then ("", false) is +// returned. +func (n *Name) GetEntry(nid NID) (entry string, ok bool) { + entrylen := C.X509_NAME_get_text_by_NID(n.name, C.int(nid), nil, 0) + if entrylen == -1 { + return "", false + } + buf := (*C.char)(C.malloc(C.size_t(entrylen + 1))) + defer C.free(unsafe.Pointer(buf)) + C.X509_NAME_get_text_by_NID(n.name, C.int(nid), buf, entrylen+1) + return C.GoStringN(buf, entrylen), true +} + // NewCertificate generates a basic certificate based // on the provided CertificateInfo struct func NewCertificate(info *CertificateInfo, key PublicKey) (*Certificate, error) { @@ -193,8 +207,20 @@ func (c *Certificate) SetIssuerName(name *Name) error { } // SetSerial sets the serial of a certificate. -func (c *Certificate) SetSerial(serial int) error { - if C.ASN1_INTEGER_set(C.X509_get_serialNumber(c.x), C.long(serial)) != 1 { +func (c *Certificate) SetSerial(serial *big.Int) error { + sno := C.ASN1_INTEGER_new() + defer C.ASN1_INTEGER_free(sno) + bn := C.BN_new() + defer C.BN_free(bn) + + serialBytes := serial.Bytes() + if bn = C.BN_bin2bn((*C.uchar)(unsafe.Pointer(&serialBytes[0])), C.int(len(serialBytes)), bn); bn == nil { + return errors.New("failed to set serial") + } + if sno = C.BN_to_ASN1_INTEGER(bn, sno); sno == nil { + return errors.New("failed to set serial") + } + if C.X509_set_serialNumber(c.x, sno) != 1 { return errors.New("failed to set serial") } return nil diff --git a/vendor/src/github.com/spacemonkeygo/openssl/cert_test.go b/vendor/src/github.com/spacemonkeygo/openssl/cert_test.go index 0dfac375ae7..c32883ba4eb 100644 --- a/vendor/src/github.com/spacemonkeygo/openssl/cert_test.go +++ b/vendor/src/github.com/spacemonkeygo/openssl/cert_test.go @@ -15,6 +15,7 @@ package openssl import ( + "math/big" "testing" "time" ) @@ -25,7 +26,7 @@ func TestCertGenerate(t *testing.T) { t.Fatal(err) } info := &CertificateInfo{ - Serial: 1, + Serial: big.NewInt(int64(1)), Issued: 0, Expires: 24 * time.Hour, Country: "US", @@ -47,7 +48,7 @@ func TestCAGenerate(t *testing.T) { t.Fatal(err) } info := &CertificateInfo{ - Serial: 1, + Serial: big.NewInt(int64(1)), Issued: 0, Expires: 24 * time.Hour, Country: "US", @@ -74,7 +75,7 @@ func TestCAGenerate(t *testing.T) { t.Fatal(err) } info = &CertificateInfo{ - Serial: 1, + Serial: big.NewInt(int64(1)), Issued: 0, Expires: 24 * time.Hour, Country: "US", @@ -99,3 +100,40 @@ func TestCAGenerate(t *testing.T) { t.Fatal(err) } } + +func TestCertGetNameEntry(t *testing.T) { + key, err := GenerateRSAKey(2048) + if err != nil { + t.Fatal(err) + } + info := &CertificateInfo{ + Serial: big.NewInt(int64(1)), + Issued: 0, + Expires: 24 * time.Hour, + Country: "US", + Organization: "Test", + CommonName: "localhost", + } + cert, err := NewCertificate(info, key) + if err != nil { + t.Fatal(err) + } + name, err := cert.GetSubjectName() + if err != nil { + t.Fatal(err) + } + entry, ok := name.GetEntry(NID_commonName) + if !ok { + t.Fatal("no common name") + } + if entry != "localhost" { + t.Fatalf("expected localhost; got %q", entry) + } + entry, ok = name.GetEntry(NID_localityName) + if ok { + t.Fatal("did not expect a locality name") + } + if entry != "" { + t.Fatalf("entry should be empty; got %q", entry) + } +} diff --git a/vendor/src/github.com/spacemonkeygo/openssl/conn.go b/vendor/src/github.com/spacemonkeygo/openssl/conn.go index 55a4b6cb67c..afc73a50ae3 100644 --- a/vendor/src/github.com/spacemonkeygo/openssl/conn.go +++ b/vendor/src/github.com/spacemonkeygo/openssl/conn.go @@ -16,25 +16,28 @@ package openssl -// #include -// #include -// #include -// #include -// -// int sk_X509_num_not_a_macro(STACK_OF(X509) *sk) { return sk_X509_num(sk); } -// X509 *sk_X509_value_not_a_macro(STACK_OF(X509)* sk, int i) { -// return sk_X509_value(sk, i); -// } -// long SSL_set_tlsext_host_name_not_a_macro(SSL *ssl, const char *name) { -// return SSL_set_tlsext_host_name(ssl, name); -// } -// const char * SSL_get_cipher_name_not_a_macro(const SSL *ssl) { -// return SSL_get_cipher_name(ssl); -// } +/* +#include +#include +#include +#include + +int sk_X509_num_not_a_macro(STACK_OF(X509) *sk) { return sk_X509_num(sk); } +X509 *sk_X509_value_not_a_macro(STACK_OF(X509)* sk, int i) { + return sk_X509_value(sk, i); +} +const char * SSL_get_cipher_name_not_a_macro(const SSL *ssl) { + return SSL_get_cipher_name(ssl); +} +static int SSL_session_reused_not_a_macro(SSL *ssl) { + return SSL_session_reused(ssl); +} +*/ import "C" import ( "errors" + "fmt" "io" "net" "runtime" @@ -381,11 +384,13 @@ type ConnectionState struct { CertificateError error CertificateChain []*Certificate CertificateChainError error + SessionReused bool } func (c *Conn) ConnectionState() (rv ConnectionState) { rv.Certificate, rv.CertificateError = c.PeerCertificate() rv.CertificateChain, rv.CertificateChainError = c.PeerCertificateChain() + rv.SessionReused = c.SessionReused() return } @@ -565,17 +570,56 @@ func (c *Conn) UnderlyingConn() net.Conn { return c.conn } -func (c *Conn) SetTlsExtHostName(name string) error { - cname := C.CString(name) - defer C.free(unsafe.Pointer(cname)) +func (c *Conn) VerifyResult() VerifyResult { + return VerifyResult(C.SSL_get_verify_result(c.ssl)) +} + +func (c *Conn) SessionReused() bool { + return C.SSL_session_reused_not_a_macro(c.ssl) == 1 +} + +func (c *Conn) GetSession() ([]byte, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if C.SSL_set_tlsext_host_name_not_a_macro(c.ssl, cname) == 0 { - return errorFromErrorQueue() + + // get1 increases the refcount of the session, so we have to free it. + session := (*C.SSL_SESSION)(C.SSL_get1_session(c.ssl)) + if session == nil { + return nil, errors.New("failed to get session") } - return nil + defer C.SSL_SESSION_free(session) + + // get the size of the encoding + slen := C.i2d_SSL_SESSION(session, nil) + + buf := (*C.uchar)(C.malloc(C.size_t(slen))) + defer C.free(unsafe.Pointer(buf)) + + // this modifies the value of buf (seriously), so we have to pass in a temp + // var so that we can actually read the bytes from buf. + tmp := buf + slen2 := C.i2d_SSL_SESSION(session, &tmp) + if slen != slen2 { + return nil, errors.New("session had different lengths") + } + + return C.GoBytes(unsafe.Pointer(buf), slen), nil } -func (c *Conn) VerifyResult() VerifyResult { - return VerifyResult(C.SSL_get_verify_result(c.ssl)) +func (c *Conn) setSession(session []byte) error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ptr := (*C.uchar)(&session[0]) + s := C.d2i_SSL_SESSION(nil, &ptr, C.long(len(session))) + if s == nil { + return fmt.Errorf("unable to load session: %s", errorFromErrorQueue()) + } + defer C.SSL_SESSION_free(s) + + ret := C.SSL_set_session(c.ssl, s) + if ret != 1 { + return fmt.Errorf("unable to set session: %s", errorFromErrorQueue()) + } + return nil } diff --git a/vendor/src/github.com/spacemonkeygo/openssl/ctx.go b/vendor/src/github.com/spacemonkeygo/openssl/ctx.go index c1aa4cc706a..e8c1824f808 100644 --- a/vendor/src/github.com/spacemonkeygo/openssl/ctx.go +++ b/vendor/src/github.com/spacemonkeygo/openssl/ctx.go @@ -31,6 +31,10 @@ 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); } @@ -43,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); } @@ -60,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() { -#if defined(TLS1_1_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX) +#if OPENSSL_VERSION_NUMBER > 0x1000100fL && defined(TLS1_1_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX) return TLSv1_1_method(); #else return NULL; @@ -68,13 +88,17 @@ static const SSL_METHOD *OUR_TLSv1_1_method() { } static const SSL_METHOD *OUR_TLSv1_2_method() { -#if defined(TLS1_2_VERSION) && !defined(OPENSSL_SYSNAME_MACOSX) +#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; @@ -93,6 +117,7 @@ import ( "io/ioutil" "os" "runtime" + "time" "unsafe" "github.com/spacemonkeygo/spacelog" @@ -110,6 +135,7 @@ type Ctx struct { chain []*Certificate key PrivateKey verify_cb VerifyCallback + sni_cb TLSExtServernameCallback } //export get_ssl_ctx_idx @@ -376,6 +402,8 @@ func (c *Ctx) AddChainCertificate(cert *Certificate) error { 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 } @@ -541,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 { @@ -619,6 +651,12 @@ func (c *Ctx) ClearOptions(options Options) 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.SSL_CTX_get_options_not_a_macro(c.ctx)) +} + type Modes int const ( @@ -697,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)) } @@ -708,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() @@ -755,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)) +} diff --git a/vendor/src/github.com/spacemonkeygo/openssl/ctx_test.go b/vendor/src/github.com/spacemonkeygo/openssl/ctx_test.go new file mode 100644 index 00000000000..9644e518bf3 --- /dev/null +++ b/vendor/src/github.com/spacemonkeygo/openssl/ctx_test.go @@ -0,0 +1,48 @@ +// Copyright (C) 2014 Ryan Hileman +// +// 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 + +import ( + "testing" + "time" +) + +func TestCtxTimeoutOption(t *testing.T) { + ctx, _ := NewCtx() + oldTimeout1 := ctx.GetTimeout() + newTimeout1 := oldTimeout1 + (time.Duration(99) * time.Second) + oldTimeout2 := ctx.SetTimeout(newTimeout1) + newTimeout2 := ctx.GetTimeout() + if oldTimeout1 != oldTimeout2 { + t.Error("SetTimeout() returns something undocumented") + } + if newTimeout1 != newTimeout2 { + t.Error("SetTimeout() does not save anything to ctx") + } +} + +func TestCtxSessCacheSizeOption(t *testing.T) { + ctx, _ := NewCtx() + oldSize1 := ctx.SessGetCacheSize() + newSize1 := oldSize1 + 42 + oldSize2 := ctx.SessSetCacheSize(newSize1) + newSize2 := ctx.SessGetCacheSize() + if oldSize1 != oldSize2 { + t.Error("SessSetCacheSize() returns something undocumented") + } + if newSize1 != newSize2 { + t.Error("SessSetCacheSize() does not save anything to ctx") + } +} diff --git a/vendor/src/github.com/spacemonkeygo/openssl/digest.go b/vendor/src/github.com/spacemonkeygo/openssl/digest.go new file mode 100644 index 00000000000..44d4d001b13 --- /dev/null +++ b/vendor/src/github.com/spacemonkeygo/openssl/digest.go @@ -0,0 +1,53 @@ +// Copyright (C) 2015 Space Monkey, Inc. +// +// 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. + +// +build cgo + +package openssl + +// #include +import "C" + +import ( + "fmt" + "unsafe" +) + +// Digest represents and openssl message digest. +type Digest struct { + ptr *C.EVP_MD +} + +// GetDigestByName returns the Digest with the name or nil and an error if the +// digest was not found. +func GetDigestByName(name string) (*Digest, error) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + p := C.EVP_get_digestbyname(cname) + if p == nil { + return nil, fmt.Errorf("Digest %v not found", name) + } + // we can consider digests to use static mem; don't need to free + return &Digest{ptr: p}, nil +} + +// GetDigestByName returns the Digest with the NID or nil and an error if the +// digest was not found. +func GetDigestByNid(nid NID) (*Digest, error) { + sn, err := Nid2ShortName(nid) + if err != nil { + return nil, err + } + return GetDigestByName(sn) +} diff --git a/vendor/src/github.com/spacemonkeygo/openssl/key.go b/vendor/src/github.com/spacemonkeygo/openssl/key.go index ec6d7805824..c69a101631f 100644 --- a/vendor/src/github.com/spacemonkeygo/openssl/key.go +++ b/vendor/src/github.com/spacemonkeygo/openssl/key.go @@ -244,6 +244,43 @@ func LoadPrivateKeyFromPEM(pem_block []byte) (PrivateKey, error) { return p, nil } +// LoadPrivateKeyFromPEM loads a private key from a PEM-encoded block. +func LoadPrivateKeyFromPEMWidthPassword(pem_block []byte, password string) ( + PrivateKey, error) { + if len(pem_block) == 0 { + return nil, errors.New("empty pem block") + } + bio := C.BIO_new_mem_buf(unsafe.Pointer(&pem_block[0]), + C.int(len(pem_block))) + if bio == nil { + return nil, errors.New("failed creating bio") + } + defer C.BIO_free(bio) + cs := C.CString(password) + defer C.free(unsafe.Pointer(cs)) + rsakey := C.PEM_read_bio_RSAPrivateKey(bio, nil, nil, unsafe.Pointer(cs)) + if rsakey == nil { + return nil, errors.New("failed reading rsa key") + } + defer C.RSA_free(rsakey) + + // convert to PKEY + key := C.EVP_PKEY_new() + if key == nil { + return nil, errors.New("failed converting to evp_pkey") + } + if C.EVP_PKEY_set1_RSA(key, (*C.struct_rsa_st)(rsakey)) != 1 { + C.EVP_PKEY_free(key) + return nil, errors.New("failed converting to evp_pkey") + } + + p := &pKey{key: key} + runtime.SetFinalizer(p, func(p *pKey) { + C.EVP_PKEY_free(p.key) + }) + return p, nil +} + // LoadPublicKeyFromPEM loads a public key from a PEM-encoded block. func LoadPublicKeyFromPEM(pem_block []byte) (PublicKey, error) { if len(pem_block) == 0 { diff --git a/vendor/src/github.com/spacemonkeygo/openssl/net.go b/vendor/src/github.com/spacemonkeygo/openssl/net.go index 275f5c27b97..3cdd040d4d4 100644 --- a/vendor/src/github.com/spacemonkeygo/openssl/net.go +++ b/vendor/src/github.com/spacemonkeygo/openssl/net.go @@ -77,6 +77,25 @@ const ( // This library is not nice enough to use the system certificate store by // default for you yet. func Dial(network, addr string, ctx *Ctx, flags DialFlags) (*Conn, error) { + return DialSession(network, addr, ctx, flags, nil) +} + +// DialSession will connect to network/address and then wrap the corresponding +// underlying connection with an OpenSSL client connection using context ctx. +// If flags includes InsecureSkipHostVerification, the server certificate's +// hostname will not be checked to match the hostname in addr. Otherwise, flags +// should be 0. +// +// Dial probably won't work for you unless you set a verify location or add +// some certs to the certificate store of the client context you're using. +// This library is not nice enough to use the system certificate store by +// default for you yet. +// +// If session is not nil it will be used to resume the tls state. The session +// can be retrieved from the GetSession method on the Conn. +func DialSession(network, addr string, ctx *Ctx, flags DialFlags, + session []byte) (*Conn, error) { + host, _, err := net.SplitHostPort(addr) if err != nil { return nil, err diff --git a/vendor/src/github.com/spacemonkeygo/openssl/old_openssl_compat.go b/vendor/src/github.com/spacemonkeygo/openssl/old_openssl_compat.go deleted file mode 100644 index 028f13bdcc0..00000000000 --- a/vendor/src/github.com/spacemonkeygo/openssl/old_openssl_compat.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2014 Space Monkey, Inc. -// -// 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. - -// +build !darwin brew -// +build cgo - -package openssl - -// #include -import "C" - -// these constants do not exist in the openssl version packaged with os x. when -// darwin decides to update the base openssl version, we can move these back -// to the appropriate spots in the source. as a workaround, if you need access -// to these constants on darwin, use homebrew or whatever to install a more -// recent version of os x, and build the package with the '-tags brew' flag - -const ( - UnsupportedConstraintSyntax VerifyResult = C.X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX - UnsupportedConstraintType VerifyResult = C.X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE - UnsupportedExtensionFeature VerifyResult = C.X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE - ExcludedViolation VerifyResult = C.X509_V_ERR_EXCLUDED_VIOLATION - SubtreeMinmax VerifyResult = C.X509_V_ERR_SUBTREE_MINMAX - UnsupportedNameSyntax VerifyResult = C.X509_V_ERR_UNSUPPORTED_NAME_SYNTAX - DifferentCrlScope VerifyResult = C.X509_V_ERR_DIFFERENT_CRL_SCOPE - PermittedViolation VerifyResult = C.X509_V_ERR_PERMITTED_VIOLATION - CrlPathValidationError VerifyResult = C.X509_V_ERR_CRL_PATH_VALIDATION_ERROR -) - -const ( - NoTLSv1_1 Options = C.SSL_OP_NO_TLSv1_1 - NoTLSv1_2 Options = C.SSL_OP_NO_TLSv1_2 -) diff --git a/vendor/src/github.com/spacemonkeygo/openssl/sni.c b/vendor/src/github.com/spacemonkeygo/openssl/sni.c new file mode 100644 index 00000000000..5398da869b8 --- /dev/null +++ b/vendor/src/github.com/spacemonkeygo/openssl/sni.c @@ -0,0 +1,23 @@ +// Copyright (C) 2014 Space Monkey, Inc. +// +// 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. + +#include +#include "_cgo_export.h" +#include + +int sni_cb(SSL *con, int *ad, void *arg) { + SSL_CTX* ssl_ctx = ssl_ctx = SSL_get_SSL_CTX(con); + void* p = SSL_CTX_get_ex_data(ssl_ctx, get_ssl_ctx_idx()); + return sni_cb_thunk(p, con, ad, arg); +} diff --git a/vendor/src/github.com/spacemonkeygo/openssl/sni_test.go b/vendor/src/github.com/spacemonkeygo/openssl/sni_test.go new file mode 100644 index 00000000000..ee3b1a8bbaf --- /dev/null +++ b/vendor/src/github.com/spacemonkeygo/openssl/sni_test.go @@ -0,0 +1,23 @@ +// Copyright (C) 2014 Space Monkey, Inc. +// +// 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 + +import "fmt" + +// We can implemant SNI rfc6066 (http://tools.ietf.org/html/rfc6066) on the server side using foolowing callback. +// You should implement context storage (tlsCtxStorage) by your self. +func ExampleSetTLSExtServernameCallback() { + fmt.Println("Hello") +} diff --git a/vendor/src/github.com/spacemonkeygo/openssl/ssl.go b/vendor/src/github.com/spacemonkeygo/openssl/ssl.go new file mode 100644 index 00000000000..d6120e15d99 --- /dev/null +++ b/vendor/src/github.com/spacemonkeygo/openssl/ssl.go @@ -0,0 +1,167 @@ +// Copyright (C) 2014 Space Monkey, Inc. +// +// 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. + +// +build cgo + +package openssl + +/* +#include +#include +#include +#include + +static long SSL_set_options_not_a_macro(SSL* ssl, long options) { + return SSL_set_options(ssl, options); +} + +static long SSL_get_options_not_a_macro(SSL* ssl) { + return SSL_get_options(ssl); +} + +static long SSL_clear_options_not_a_macro(SSL* ssl, long options) { + return SSL_clear_options(ssl, options); +} + +extern int verify_ssl_cb(int ok, X509_STORE_CTX* store); +*/ +import "C" + +import ( + "os" + "unsafe" +) + +type SSLTLSExtErr int + +var ( + ssl_idx = C.SSL_get_ex_new_index(0, nil, nil, nil, nil) +) + +//export get_ssl_idx +func get_ssl_idx() C.int { + return ssl_idx +} + +type SSL struct { + ssl *C.SSL + verify_cb VerifyCallback +} + +//export verify_ssl_cb_thunk +func verify_ssl_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 := (*SSL)(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 +} + +// GetOptions returns SSL options. See +// https://www.openssl.org/docs/ssl/SSL_CTX_set_options.html +func (s *SSL) GetOptions() Options { + return Options(C.SSL_get_options_not_a_macro(s.ssl)) +} + +// SetOptions sets SSL options. See +// https://www.openssl.org/docs/ssl/SSL_CTX_set_options.html +func (s *SSL) SetOptions(options Options) Options { + return Options(C.SSL_set_options_not_a_macro(s.ssl, C.long(options))) +} + +// ClearOptions clear SSL options. See +// https://www.openssl.org/docs/ssl/SSL_CTX_set_options.html +func (s *SSL) ClearOptions(options Options) Options { + return Options(C.SSL_clear_options_not_a_macro(s.ssl, C.long(options))) +} + +// SetVerify controls peer verification settings. See +// http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html +func (s *SSL) SetVerify(options VerifyOptions, verify_cb VerifyCallback) { + s.verify_cb = verify_cb + if verify_cb != nil { + C.SSL_set_verify(s.ssl, C.int(options), (*[0]byte)(C.verify_ssl_cb)) + } else { + C.SSL_set_verify(s.ssl, C.int(options), nil) + } +} + +// SetVerifyMode controls peer verification setting. See +// http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html +func (s *SSL) SetVerifyMode(options VerifyOptions) { + s.SetVerify(options, s.verify_cb) +} + +// SetVerifyCallback controls peer verification setting. See +// http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html +func (s *SSL) SetVerifyCallback(verify_cb VerifyCallback) { + s.SetVerify(s.VerifyMode(), s.verify_cb) +} + +// GetVerifyCallback returns callback function. See +// http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html +func (s *SSL) GetVerifyCallback() VerifyCallback { + return s.verify_cb +} + +// VerifyMode returns peer verification setting. See +// http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html +func (s *SSL) VerifyMode() VerifyOptions { + return VerifyOptions(C.SSL_get_verify_mode(s.ssl)) +} + +// 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 (s *SSL) SetVerifyDepth(depth int) { + C.SSL_set_verify_depth(s.ssl, 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 (s *SSL) GetVerifyDepth() int { + return int(C.SSL_get_verify_depth(s.ssl)) +} + +//export sni_cb_thunk +func sni_cb_thunk(p unsafe.Pointer, con *C.SSL, ad unsafe.Pointer, arg unsafe.Pointer) C.int { + defer func() { + if err := recover(); err != nil { + logger.Critf("openssl: verify callback sni panic'd: %v", err) + os.Exit(1) + } + }() + + sni_cb := (*Ctx)(p).sni_cb + + s := &SSL{ssl: con} + // This attaches a pointer to our SSL struct into the SNI callback. + C.SSL_set_ex_data(s.ssl, get_ssl_idx(), unsafe.Pointer(s)) + + // Note: this is ctx.sni_cb, not C.sni_cb + return C.int(sni_cb(s)) +} diff --git a/vendor/src/github.com/spacemonkeygo/openssl/verify.c b/vendor/src/github.com/spacemonkeygo/openssl/verify.c index bfc626812cd..d55866c4cf0 100644 --- a/vendor/src/github.com/spacemonkeygo/openssl/verify.c +++ b/vendor/src/github.com/spacemonkeygo/openssl/verify.c @@ -14,12 +14,18 @@ #include #include "_cgo_export.h" -#include int verify_cb(int ok, X509_STORE_CTX* store) { SSL* ssl = (SSL *)X509_STORE_CTX_get_app_data(store); - SSL_CTX* ssl_ctx = ssl_ctx = SSL_get_SSL_CTX(ssl); + SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl); void* p = SSL_CTX_get_ex_data(ssl_ctx, get_ssl_ctx_idx()); // get the pointer to the go Ctx object and pass it back into the thunk return verify_cb_thunk(p, ok, store); } + +int verify_ssl_cb(int ok, X509_STORE_CTX* store) { + SSL* ssl = (SSL *)X509_STORE_CTX_get_app_data(store); + void* p = SSL_get_ex_data(ssl, get_ssl_idx()); + // get the pointer to the go Ctx object and pass it back into the thunk + return verify_ssl_cb_thunk(p, ok, store); +} -- cgit v1.2.1