github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/orderer/sbft/connection/connection.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package connection 18 19 import ( 20 "crypto/sha256" 21 "crypto/tls" 22 "crypto/x509" 23 "fmt" 24 "net" 25 26 "google.golang.org/grpc" 27 "google.golang.org/grpc/credentials" 28 "google.golang.org/grpc/peer" 29 "google.golang.org/grpc/transport" 30 ) 31 32 type PeerInfo struct { 33 addr string 34 cert *x509.Certificate 35 cp *x509.CertPool 36 } 37 38 type Manager struct { 39 Server *grpc.Server 40 Listener net.Listener 41 Self PeerInfo 42 tlsConfig *tls.Config 43 Cert *tls.Certificate 44 } 45 46 func New(addr string, certFile string, keyFile string) (_ *Manager, err error) { 47 c := &Manager{} 48 49 cert, err := tls.LoadX509KeyPair(certFile, keyFile) 50 if err != nil { 51 return nil, err 52 } 53 cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0]) 54 if err != nil { 55 return nil, err 56 } 57 58 c.Cert = &cert 59 c.Self, err = NewPeerInfo("", cert.Certificate[0]) 60 61 c.tlsConfig = &tls.Config{ 62 Certificates: []tls.Certificate{cert}, 63 ClientAuth: tls.RequestClientCert, 64 InsecureSkipVerify: true, 65 } 66 67 c.Listener, err = net.Listen("tcp", addr) 68 if err != nil { 69 return nil, err 70 } 71 72 serverTls := c.tlsConfig 73 serverTls.ServerName = addr 74 c.Server = grpc.NewServer(grpc.Creds(credentials.NewTLS(serverTls))) 75 go c.Server.Serve(c.Listener) 76 return c, nil 77 } 78 79 func (c *Manager) DialPeer(peer PeerInfo, opts ...grpc.DialOption) (*grpc.ClientConn, error) { 80 return dialPeer(&c.tlsConfig.Certificates[0], peer, opts...) 81 } 82 83 // to check client: credentials.FromContext() -> AuthInfo 84 85 type patchedAuthenticator struct { 86 credentials.TransportCredentials 87 pinnedCert *x509.Certificate 88 tunneledError error 89 } 90 91 func dialPeer(cert *tls.Certificate, peer PeerInfo, opts ...grpc.DialOption) (*grpc.ClientConn, error) { 92 clientTLS := &tls.Config{InsecureSkipVerify: true} 93 if cert != nil { 94 clientTLS.Certificates = []tls.Certificate{*cert} 95 } 96 97 creds := credentials.NewTLS(clientTLS) 98 patchedCreds := &patchedAuthenticator{ 99 TransportCredentials: creds, 100 pinnedCert: peer.cert, 101 } 102 opts = append(opts, grpc.WithTransportCredentials(patchedCreds)) 103 conn, err := grpc.Dial(peer.addr, opts...) 104 if err != nil { 105 if patchedCreds.tunneledError != nil { 106 err = patchedCreds.tunneledError 107 } 108 return nil, err 109 } 110 111 return conn, nil 112 } 113 114 func DialPeer(peer PeerInfo, opts ...grpc.DialOption) (*grpc.ClientConn, error) { 115 return dialPeer(nil, peer, opts...) 116 } 117 118 func GetPeerInfo(s grpc.Stream) PeerInfo { 119 var pi PeerInfo 120 121 ctx := s.Context() 122 trs, ok := transport.StreamFromContext(ctx) 123 if ok { 124 pi.addr = trs.ServerTransport().RemoteAddr().String() 125 } 126 127 p, _ := peer.FromContext(ctx) 128 switch creds := p.AuthInfo.(type) { 129 case credentials.TLSInfo: 130 state := creds.State 131 if len(state.PeerCertificates) > 0 { 132 pi.cert = state.PeerCertificates[0] 133 } 134 } 135 136 return pi 137 } 138 139 func NewPeerInfo(addr string, cert []byte) (_ PeerInfo, err error) { 140 var p PeerInfo 141 142 p.addr = addr 143 p.cert, err = x509.ParseCertificate(cert) 144 if err != nil { 145 return 146 } 147 p.cp = x509.NewCertPool() 148 p.cp.AddCert(p.cert) 149 return p, nil 150 } 151 152 func (pi *PeerInfo) Fingerprint() string { 153 return fmt.Sprintf("%x", sha256.Sum256(pi.cert.Raw)) 154 } 155 156 func (pi *PeerInfo) Cert() *x509.Certificate { 157 cert := *pi.cert 158 return &cert 159 } 160 161 func (pi PeerInfo) String() string { 162 return fmt.Sprintf("%.6s [%s]", pi.Fingerprint(), pi.addr) 163 }