Skip to content

Commit

Permalink
Merge pull request #197 from gravitational/alexander/bughunt2
Browse files Browse the repository at this point in the history
fixing bugs, refs #180
  • Loading branch information
klizhentas committed Mar 4, 2016
2 parents f874789 + 26331fb commit 61ce5ec
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 133 deletions.
4 changes: 2 additions & 2 deletions lib/auth/api_with_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,12 @@ func (socket *fakeSocket) CreateBridge(remoteAddr net.Addr, sshChan ssh.Channel)
// Accept() will unblock this select
case socket.connections <- connection:
}

log.Debugf("SocketOverSSH.Handle(from=%v) is accepted", remoteAddr)
// wait for the connection to close:
select {
case <-connection.closed:
}
log.Debugf("SocketOverSSH.Handle(from=%v) is done", remoteAddr)
log.Debugf("SocketOverSSH.Handle(from=%v) is closed", remoteAddr)
return nil
}

Expand Down
113 changes: 56 additions & 57 deletions lib/auth/tun.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package auth
import (
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"os"
Expand Down Expand Up @@ -364,7 +365,7 @@ func (s *AuthTunnel) passwordAuth(
switch ab.Type {
case AuthWebPassword:
if err := s.authServer.CheckPassword(conn.User(), ab.Pass, ab.HotpToken); err != nil {
log.Errorf("Password auth error: %v", err)
log.Warningf("password auth error: %v", err)
return nil, trace.Wrap(err)
}
perms := &ssh.Permissions{
Expand Down Expand Up @@ -510,7 +511,7 @@ func NewTunClient(addr utils.NetAddr, user string, auth []ssh.AuthMethod) (*TunC
return tc, nil
}

func (c *TunClient) GetAgent() (agent.Agent, error) {
func (c *TunClient) GetAgent() (AgentCloser, error) {
return c.dialer.GetAgent()
}

Expand All @@ -525,63 +526,60 @@ func (c *TunClient) GetDialer() AccessPointDialer {
}
}

type AgentCloser interface {
io.Closer
agent.Agent
}

type tunAgent struct {
agent.Agent
client *ssh.Client
}

func (ta *tunAgent) Close() error {
log.Infof("tunAgent.Close")
return ta.client.Close()
}

type TunDialer struct {
sync.Mutex
auth []ssh.AuthMethod
user string
tun *ssh.Client
addr utils.NetAddr
}

func (t *TunDialer) Close() error {
if t.tun != nil {
return t.tun.Close()
}
return nil
}

func (t *TunDialer) GetAgent() (agent.Agent, error) {
_, err := t.getClient(false) // we need an established connection first
func (t *TunDialer) GetAgent() (AgentCloser, error) {
client, err := t.getClient() // we need an established connection first
if err != nil {
return nil, trace.Wrap(err)
return nil, trace.Wrap(
teleport.ConnectionProblem("failed to connect to remote API", err))
}
ch, _, err := t.tun.OpenChannel(ReqWebSessionAgent, nil)
ch, _, err := client.OpenChannel(ReqWebSessionAgent, nil)
if err != nil {
// reconnecting and trying again
_, err := t.getClient(true)
if err != nil {
return nil, trace.Wrap(err)
}
ch, _, err = t.tun.OpenChannel(ReqWebSessionAgent, nil)
if err != nil {
return nil, trace.Wrap(err)
}
return nil, trace.Wrap(
teleport.ConnectionProblem("failed to connect to remote API", err))
}
log.Infof("opened agent channel")
return agent.NewClient(ch), nil
agentCloser := &tunAgent{client: client}
agentCloser.Agent = agent.NewClient(ch)
return agentCloser, nil
}

func (t *TunDialer) getClient(reset bool) (*ssh.Client, error) {
t.Lock()
defer t.Unlock()
if t.tun != nil {
if !reset {
return t.tun, nil
}
go t.tun.Close()
t.tun = nil
}
func (t *TunDialer) getClient() (*ssh.Client, error) {
config := &ssh.ClientConfig{
User: t.user,
Auth: t.auth,
}
client, err := ssh.Dial(t.addr.AddrNetwork, t.addr.Addr, config)
log.Infof("TunDialer.getClient(%v)", t.addr.String())
if err != nil {
log.Infof("TunDialer could not ssh.Dial: %v", err)
return nil, trace.Wrap(err)
}
t.tun = client
return t.tun, nil
return client, nil
}

const (
Expand All @@ -592,32 +590,33 @@ const (
DialerPeriodBetweenAttempts = time.Second
)

type tunConn struct {
net.Conn
client *ssh.Client
}

func (c *tunConn) Close() error {
log.Infof("tunConn: close!")
err := c.Conn.Close()
err = c.client.Close()
return trace.Wrap(err)
}

func (t *TunDialer) Dial(network, address string) (net.Conn, error) {
var client *ssh.Client
var err error
for i := 0; i < DialerRetryAttempts; i++ {
if i == 0 {
client, err = t.getClient(false)
if err != nil {
log.Infof("TunDialer failed to get client: %v", err)
continue
}
} else {
time.Sleep(DialerPeriodBetweenAttempts)
client, err = t.getClient(true)
if err != nil {
log.Infof("TunDialer failed to get client: %v", err)
continue
}
}
conn, err := client.Dial(network, address)
if err == nil {
return conn, nil
}
log.Infof("TunDialer connection issue (%v), reconnect", err)
log.Infof("TunDialer.Dial(%v, %v)", network, address)
client, err := t.getClient()
if err != nil {
return nil, trace.Wrap(
teleport.ConnectionProblem("failed to connect to remote API", err))
}
return nil, trace.Wrap(
teleport.ConnectionProblem("failed to connect to remote API", err))
conn, err := client.Dial(network, address)
if err != nil {
return nil, trace.Wrap(
teleport.ConnectionProblem("failed to connect to remote API", err))
}
tc := &tunConn{client: client}
tc.Conn = conn
return tc, nil
}

func NewClientFromSSHClient(sshClient *ssh.Client) (*Client, error) {
Expand Down
2 changes: 1 addition & 1 deletion lib/hangout/hangout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ type HangoutsSuite struct {
var _ = Suite(&HangoutsSuite{})

func (s *HangoutsSuite) SetUpSuite(c *C) {
utils.InitLoggerDebug()
utils.InitLoggerCLI()
client.KeysDir = c.MkDir()
s.dir = c.MkDir()

Expand Down
51 changes: 35 additions & 16 deletions lib/reversetunnel/srv.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ func (s *server) upsertRegularSite(conn net.Conn, sshConn *ssh.ServerConn) (*tun
return nil, trace.Wrap(teleport.BadParameter(
"authDomain", fmt.Sprintf("'%v' is a bad domain name", domainName)))
}

s.Lock()
defer s.Unlock()

var site *tunnelSite
for _, st := range s.tunnelSites {
if st.domainName == domainName {
Expand All @@ -371,9 +375,6 @@ func (s *server) upsertRegularSite(conn net.Conn, sshConn *ssh.ServerConn) (*tun
}
log.Infof("found authority domain: %v", domainName)

s.Lock()
defer s.Unlock()

var err error
if site != nil {
if err := site.addConn(conn, sshConn); err != nil {
Expand All @@ -392,16 +393,24 @@ func (s *server) upsertRegularSite(conn net.Conn, sshConn *ssh.ServerConn) (*tun
return site, nil
}

func (s *server) upsertHangoutSite(conn net.Conn, sshConn ssh.Conn) (*tunnelSite, error) {
func (s *server) tryInsertHangoutSite(hangoutID string, remoteSite *tunnelSite) error {
s.Lock()
defer s.Unlock()

hangoutID := sshConn.User()
for _, st := range s.tunnelSites {
if st.domainName == hangoutID {
return nil, trace.Errorf("Hangout ID is already used")
return trace.Wrap(
teleport.BadParameter("hangoutID",
fmt.Sprintf("%v hangout id is already used", hangoutID)))
}
}
s.tunnelSites = append(s.tunnelSites, remoteSite)
return nil

}

func (s *server) upsertHangoutSite(conn net.Conn, sshConn ssh.Conn) (*tunnelSite, error) {
hangoutID := sshConn.User()

site, err := newRemoteSite(s, hangoutID)
if err != nil {
Expand Down Expand Up @@ -441,26 +450,36 @@ func (s *server) upsertHangoutSite(conn net.Conn, sshConn ssh.Conn) (*tunnelSite
}

// receiving hangoutInfo using sessions just as storage
sess, err := clt.GetSessions()
sessions, err := clt.GetSessions()
if err != nil {
return nil, trace.Wrap(err)
}
if len(sess) != 1 {
return nil, trace.Wrap(&teleport.NotFoundError{
Message: fmt.Sprintf("hangout %v not found", hangoutID),
})
var hangoutInfo *utils.HangoutInfo
for _, sess := range sessions {
info, err := utils.UnmarshalHangoutInfo(sess.ID)
if err != nil {
log.Infof("failed to unmarshal hangout info: %v", err)
}
if info.HangoutID == hangoutID {
hangoutInfo = info
break
}
}
hangoutInfo, err := utils.UnmarshalHangoutInfo(sess[0].ID)
if err != nil {
return nil, err
if hangoutInfo == nil {
return nil, trace.Wrap(teleport.NotFound(
fmt.Sprintf("hangout %v not found", hangoutID)))
}
site.domainName = hangoutInfo.HangoutID

// TODO(klizhentas) refactor this
site.domainName = hangoutInfo.HangoutID
site.hangoutInfo.OSUser = hangoutInfo.OSUser
site.hangoutInfo.AuthPort = hangoutInfo.AuthPort
site.hangoutInfo.NodePort = hangoutInfo.NodePort

s.tunnelSites = append(s.tunnelSites, site)
if err := s.tryInsertHangoutSite(hangoutID, site); err != nil {
defer conn.Close()
return nil, trace.Wrap(err)
}
return site, nil
}

Expand Down
1 change: 0 additions & 1 deletion lib/services/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,6 @@ func (s *WebService) CheckPassword(user string, password []byte, hotpToken strin
if err != nil {
return trace.Wrap(err)
}

if !otp.Scan(hotpToken, 4) {
return &teleport.BadParameterError{Err: "tokens do not match", Param: "token"}
}
Expand Down
3 changes: 2 additions & 1 deletion lib/srv/sess.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ func newSession(id string, r *sessionRegistry, context *ctx) (*session, error) {
login: context.login,
closeC: make(chan bool),
}
go sess.pollAndSyncTerm()
return sess, nil
}

Expand Down Expand Up @@ -282,6 +281,7 @@ func (s *session) start(sconn *ssh.ServerConn, ch ssh.Channel, ctx *ctx) error {
return trace.Wrap(err)
}
}
go s.pollAndSyncTerm()
cmd := exec.Command(s.registry.srv.shell)
// TODO(klizhentas) figure out linux user policy for launching shells,
// what user and environment should we use to execute the shell? the simplest
Expand Down Expand Up @@ -377,6 +377,7 @@ func (s *session) syncTerm(sessionServer rsession.Service) error {
log.Infof("syncTerm: no session")
return trace.Wrap(err)
}
log.Infof("syncTerm: term: %v", s.term)
winSize, err := s.term.getWinsize()
if err != nil {
log.Infof("syncTerm: no terminal")
Expand Down
Loading

0 comments on commit 61ce5ec

Please sign in to comment.