MCPcopy Index your code
hub / github.com/tailscale/tailscale / continueClientHandshake

Function continueClientHandshake

control/controlbase/handshake.go:120–190  ·  view source on GitHub ↗
(ctx context.Context, conn net.Conn, s *symmetricState, machineKey, machineEphemeral key.MachinePrivate, controlKey key.MachinePublic, protocolVersion uint16)

Source from the content-addressed store, hash-verified

118}
119
120func continueClientHandshake(ctx context.Context, conn net.Conn, s *symmetricState, machineKey, machineEphemeral key.MachinePrivate, controlKey key.MachinePublic, protocolVersion uint16) (*Conn, error) {
121 // No matter what, this function can only run once per s. Ensure
122 // attempted reuse causes a panic.
123 defer func() {
124 s.finished = true
125 }()
126
127 if deadline, ok := ctx.Deadline(); ok {
128 if err := conn.SetDeadline(deadline); err != nil {
129 return nil, fmt.Errorf("setting conn deadline: %w", err)
130 }
131 defer func() {
132 conn.SetDeadline(time.Time{})
133 }()
134 }
135
136 // Read in the payload and look for errors/protocol violations from the server.
137 var resp responseMessage
138 if _, err := io.ReadFull(conn, resp.Header()); err != nil {
139 return nil, fmt.Errorf("reading response header: %w", err)
140 }
141 if resp.Type() != msgTypeResponse {
142 if resp.Type() != msgTypeError {
143 return nil, fmt.Errorf("unexpected response message type %d", resp.Type())
144 }
145 msg := make([]byte, resp.Length())
146 if _, err := io.ReadFull(conn, msg); err != nil {
147 return nil, err
148 }
149 return nil, fmt.Errorf("server error: %q", msg)
150 }
151 if resp.Length() != len(resp.Payload()) {
152 return nil, fmt.Errorf("wrong length %d received for handshake response", resp.Length())
153 }
154 if _, err := io.ReadFull(conn, resp.Payload()); err != nil {
155 return nil, err
156 }
157
158 // <- e, ee, se
159 controlEphemeralPub := key.MachinePublicFromRaw32(mem.B(resp.EphemeralPub()))
160 s.MixHash(controlEphemeralPub.UntypedBytes())
161 if _, err := s.MixDH(machineEphemeral, controlEphemeralPub); err != nil {
162 return nil, fmt.Errorf("computing ee: %w", err)
163 }
164 cipher, err := s.MixDH(machineKey, controlEphemeralPub)
165 if err != nil {
166 return nil, fmt.Errorf("computing se: %w", err)
167 }
168 if err := s.DecryptAndHash(cipher, nil, resp.Tag()); err != nil {
169 return nil, fmt.Errorf("decrypting payload: %w", err)
170 }
171
172 c1, c2, err := s.Split()
173 if err != nil {
174 return nil, fmt.Errorf("finalizing handshake: %w", err)
175 }
176
177 c := &Conn{

Callers 1

ClientDeferredFunction · 0.85

Calls 15

HeaderMethod · 0.95
TypeMethod · 0.95
LengthMethod · 0.95
PayloadMethod · 0.95
EphemeralPubMethod · 0.95
TagMethod · 0.95
MachinePublicFromRaw32Function · 0.92
DeadlineMethod · 0.80
MixHashMethod · 0.80
MixDHMethod · 0.80
DecryptAndHashMethod · 0.80
SplitMethod · 0.80

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…