// Initializes a stream into an encrypted tunnel link. func (c *Connection) initClientTunnel(strm *stream.Stream, remote uint64, id uint64, key []byte, deadline time.Time) (*link.Link, error) { // Set a socket deadline for finishing the handshake strm.Sock().SetDeadline(deadline) defer strm.Sock().SetDeadline(time.Time{}) // Send the unencrypted tunnel id to associate with the remote tunnel init := &initPacket{ConnId: remote, TunId: id} if err := strm.Send(init); err != nil { return nil, err } // Create the encrypted link and authorize it hasher := func() hash.Hash { return config.HkdfHash.New() } hkdf := hkdf.New(hasher, key, config.HkdfSalt, config.HkdfInfo) conn := link.New(strm, hkdf, false) // Send and retrieve an authorization to verify both directions auth := &proto.Message{ Head: proto.Header{ Meta: &authPacket{Id: id}, }, } if err := conn.SendDirect(auth); err != nil { return nil, err } if msg, err := conn.RecvDirect(); err != nil { return nil, err } else if auth, ok := msg.Head.Meta.(*authPacket); !ok || auth.Id != id { return nil, errors.New("protocol violation") } conn.Start(config.IrisTunnelBuffer) // Return the initialized link return conn, nil }
// Creates a new, double link session for authenticated data transfer. The // initiator is used to decide the key derivation order for the channels. func newSession(conn *stream.Stream, secret []byte, server bool) *Session { // Create the key derivation function hasher := func() hash.Hash { return config.HkdfHash.New() } hkdf := hkdf.New(hasher, secret, config.HkdfSalt, config.HkdfInfo) // Create the encrypted control link return &Session{ kdf: hkdf, CtrlLink: link.New(conn, hkdf, server), } }
// Initializes a stream into an encrypted tunnel link. func (o *Overlay) initServerTunnel(strm *stream.Stream) error { // Set a socket deadline for finishing the handshake strm.Sock().SetDeadline(time.Now().Add(config.IrisTunnelInitTimeout)) defer strm.Sock().SetDeadline(time.Time{}) // Fetch the unencrypted client initiator init := new(initPacket) if err := strm.Recv(init); err != nil { return err } o.lock.RLock() c, ok := o.conns[init.ConnId] o.lock.RUnlock() if !ok { return errors.New("connection not found") } c.tunLock.RLock() tun, ok := c.tunLive[init.TunId] c.tunLock.RUnlock() if !ok { return errors.New("tunnel not found") } // Create the encrypted link hasher := func() hash.Hash { return config.HkdfHash.New() } hkdf := hkdf.New(hasher, tun.secret, config.HkdfSalt, config.HkdfInfo) conn := link.New(strm, hkdf, true) // Send and retrieve an authorization to verify both directions auth := &proto.Message{ Head: proto.Header{ Meta: &authPacket{Id: tun.id}, }, } if err := conn.SendDirect(auth); err != nil { return err } if msg, err := conn.RecvDirect(); err != nil { return err } else if auth, ok := msg.Head.Meta.(*authPacket); !ok || auth.Id != tun.id { return errors.New("protocol violation") } conn.Start(config.IrisTunnelBuffer) // Send back the initialized link to the pending tunnel select { case tun.initDone <- conn: // Connection handled by initiator return nil case <-tun.initStop: // Initiator timed out or terminated, close conn.Close() return nil // No error, since tunnel was handled, albeit not as expected } }
// Finalizes a session by creating the secondary data link. func (s *Session) init(conn *stream.Stream, server bool) { s.DataLink = link.New(conn, s.kdf, server) }