github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/tao/listener.go (about) 1 // Copyright (c) 2014, Google, Inc. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tao 16 17 import ( 18 "crypto/tls" 19 "crypto/x509" 20 "errors" 21 "net" 22 23 "github.com/jlmucb/cloudproxy/go/tao/auth" 24 "github.com/jlmucb/cloudproxy/go/util" 25 ) 26 27 // A listener implements net.Listener for Tao connections. Each time it accepts 28 // a connection, it exchanges Tao attestation chains and checks the attestation 29 // for the certificate of the client against its Guard. The guard in this 30 // case should be the guard of the Tao domain. This listener allows connections 31 // from any program that is authorized under the Tao to execute. 32 type listener struct { 33 gl net.Listener 34 guard Guard 35 verifier *Verifier 36 delegation *Attestation 37 } 38 39 // anonymousListener is like a listener, except it does not require its peer to 40 // attest to its identity. This provides a one-way authenticated TLS channel for 41 // anonymous clients to Tao-based services. 42 type anonymousListener struct { 43 listener 44 } 45 46 // Listen returns a new Tao-based net.Listener that uses the underlying 47 // crypto/tls net.Listener and a Guard to check whether or not connections 48 // are authorized. 49 func Listen(network, laddr string, config *tls.Config, g Guard, v *Verifier, del *Attestation) (net.Listener, error) { 50 config.ClientAuth = tls.RequireAnyClientCert 51 inner, err := tls.Listen(network, laddr, config) 52 if err != nil { 53 return nil, err 54 } 55 56 return &listener{inner, g, v, del}, nil 57 } 58 59 // ListenAnonymous returns a new Tao-based net.Listener that does not require 60 // its peer to attest to its identity. 61 func ListenAnonymous(network, laddr string, config *tls.Config, g Guard, v *Verifier, del *Attestation) (net.Listener, error) { 62 config.ClientAuth = tls.NoClientCert 63 inner, err := tls.Listen(network, laddr, config) 64 if err != nil { 65 return nil, err 66 } 67 68 return &anonymousListener{listener{inner, g, v, del}}, nil 69 } 70 71 // ValidatePeerAttestation checks a Attestation for a given Listener against 72 // an X.509 certificate from a TLS channel. 73 func ValidatePeerAttestation(a *Attestation, cert *x509.Certificate, guard Guard) error { 74 stmt, err := a.Validate() 75 if err != nil { 76 return err 77 } 78 79 // Insist that the message of the statement be a SpeaksFor and that the 80 // initial term be an auth.Prin of type key. Note that Validate has already 81 // checked the expirations and the times and the general well-formedness of 82 // the attestation. 83 sf, ok := stmt.Message.(auth.Speaksfor) 84 if !ok { 85 return errors.New("a peer attestation must have an auth.Speaksfor as a message") 86 } 87 88 // This key must contain the serialized X.509 certificate. 89 kprin, ok := sf.Delegate.(auth.Prin) 90 if !ok { 91 return errors.New("a peer attestation must have an auth.Prin as its delegate") 92 } 93 94 if kprin.Type != "key" { 95 return errors.New("a peer attestation must have an auth.Prin of type 'key' as its delegate") 96 } 97 98 if _, ok := kprin.KeyHash.(auth.Bytes); !ok { 99 return errors.New("a peer attestation must have a KeyHash of type auth.Bytes") 100 } 101 102 prin, ok := sf.Delegator.(auth.Prin) 103 if !ok { 104 return errors.New("a peer attestation must have an auth.Prin as its delegator") 105 } 106 107 // Ask the Tao Domain if this program is allowed to execute. 108 // TODO(tmroeder): the current implementation assumes that the Tao Guard is 109 // already able to check authorization of Execute for both programs. In 110 // general, this might not be true. 111 if !guard.IsAuthorized(prin, "Execute", nil) { 112 return errors.New("a principal delegator in a client attestation must be authorized to Execute") 113 } 114 115 // The bytes of the delegate are the result of ToPrincipal on 116 // Keys.SigningKey. Check that this represents the same key as the one 117 // in the certificate. 118 verifier, err := VerifierFromX509(cert) 119 if err != nil { 120 return err 121 } 122 if !verifier.ToPrincipal().Identical(kprin) { 123 return errors.New("a peer attestation must have an auth.Prin.KeyHash of type auth.Bytes where the bytes match the auth.Prin hash representation of the X.509 certificate") 124 } 125 126 return nil 127 } 128 129 // Accept waits for a connect, accepts it using the underlying Conn and checks 130 // the attestations and the statement. 131 func (l *listener) Accept() (net.Conn, error) { 132 c, err := l.gl.Accept() 133 if err != nil { 134 return nil, err 135 } 136 137 // Tao handshake Protocol: 138 // 0. TLS handshake (executed automatically on first message) 139 // 1. Client -> Server: Tao delegation for X.509 certificate. 140 // 2. Server: checks for a Tao-authorized program. 141 // 3. Server -> Client: Tao delegation for X.509 certificate. 142 // 4. Client: checks for a Tao-authorized program. 143 ms := util.NewMessageStream(c) 144 var a Attestation 145 if err := ms.ReadMessage(&a); err != nil { 146 c.Close() 147 return nil, err 148 } 149 150 if err := AddEndorsements(l.guard, &a, l.verifier); err != nil { 151 return nil, err 152 } 153 154 peerCert := c.(*tls.Conn).ConnectionState().PeerCertificates[0] 155 if err := ValidatePeerAttestation(&a, peerCert, l.guard); err != nil { 156 c.Close() 157 return nil, err 158 } 159 160 if _, err := ms.WriteMessage(l.delegation); err != nil { 161 c.Close() 162 return nil, err 163 } 164 165 return c, nil 166 } 167 168 // Accept waits for a connect, accepts it using the underlying Conn and checks 169 // the attestations and the statement. 170 func (l *anonymousListener) Accept() (net.Conn, error) { 171 c, err := l.gl.Accept() 172 if err != nil { 173 return nil, err 174 } 175 176 // One-way Tao handshake Protocol: 177 // 0. TLS handshake (executed automatically on first message) 178 // 1. Server -> Client: Tao delegation for X.509 certificate. 179 // 2. Client: checks for a Tao-authorized program. 180 ms := util.NewMessageStream(c) 181 182 if _, err := ms.WriteMessage(l.delegation); err != nil { 183 c.Close() 184 return nil, err 185 } 186 187 return c, nil 188 } 189 190 // Close closes the listener. 191 // Any blocked Accept operations will be unblocked and return errors. 192 // This implementation passes the Close operation down to its inner listener. 193 func (l *listener) Close() error { 194 return l.gl.Close() 195 } 196 197 // Addr returns the listener's network address. 198 func (l *listener) Addr() net.Addr { 199 return l.gl.Addr() 200 }