grim/hgkeeper
Clone
Summary
Browse
Changes
Graph
access:
access-control
2019-04-28, Wagner Riffel
bdb2c82e0679
access:
permissions: moved to its own file
yaml decoder: rolled back to old interface of taking an io.Reader
decoder: now it reads multiple keys from authrorized_keys file
all: minor syntaxy issues fixed, removed unsused variables
package
ssh
import
(
"fmt"
"net"
"bitbucket.org/rw_grim/hgkeeper/access"
log
"github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh"
)
type
Server
struct
{
cfg
*
ssh
.
ServerConfig
a
*
access
.
Access
listener
net
.
Listener
}
func
NewServer
(
hostKeysPath
,
reposPath
string
)
(
*
Server
,
error
)
{
s
:=
new
(
Server
)
s
.
cfg
=
&
ssh
.
ServerConfig
{
MaxAuthTries
:
1
,
PublicKeyCallback
:
s
.
publicKeyCallback
,
}
var
err
error
if
err
=
s
.
setHostKeysPath
(
hostKeysPath
);
err
!=
nil
{
return
nil
,
err
}
if
s
.
a
,
err
=
access
.
New
(
reposPath
);
err
!=
nil
{
return
nil
,
err
}
return
s
,
nil
}
func
(
s
*
Server
)
Listen
(
addr
string
)
error
{
listener
,
err
:=
net
.
Listen
(
"tcp"
,
addr
)
if
err
!=
nil
{
return
err
}
s
.
listener
=
listener
log
.
Infof
(
"listening for ssh connections on %s"
,
addr
)
for
{
tcpConn
,
err
:=
s
.
listener
.
Accept
()
if
err
!=
nil
{
log
.
Errorf
(
"failed to accept ssh connection: %v"
,
err
)
continue
}
sshConn
,
chans
,
reqs
,
err
:=
ssh
.
NewServerConn
(
tcpConn
,
s
.
cfg
)
if
err
!=
nil
{
log
.
Errorf
(
"ssh handshake failed: %v"
,
err
)
continue
}
log
.
Infof
(
"new ssh connection from %s(%s)"
,
sshConn
.
RemoteAddr
(),
sshConn
.
ClientVersion
())
go
ssh
.
DiscardRequests
(
reqs
)
go
s
.
processSSHChannels
(
chans
)
}
}
func
(
s
*
Server
)
publicKeyCallback
(
meta
ssh
.
ConnMetadata
,
key
ssh
.
PublicKey
)
(
*
ssh
.
Permissions
,
error
)
{
log
.
Debugf
(
"key: %s\n"
,
key
.
Marshal
())
return
nil
,
nil
}
func
(
s
*
Server
)
processSSHChannels
(
chans
<-
chan
ssh
.
NewChannel
)
{
for
ch
:=
range
chans
{
// we process each channel in a go routine as there's network traffic involved
go
s
.
processSSHChannel
(
ch
)
}
}
func
(
s
*
Server
)
processSSHChannel
(
ch
ssh
.
NewChannel
)
{
if
t
:=
ch
.
ChannelType
();
t
!=
"session"
{
ch
.
Reject
(
ssh
.
UnknownChannelType
,
fmt
.
Sprintf
(
"unsupported channel type %s"
,
t
))
return
}
conn
,
requests
,
err
:=
ch
.
Accept
()
if
err
!=
nil
{
log
.
Warnf
(
"failed to accept connection: %v"
,
err
)
return
}
defer
conn
.
Close
()
// now run through all of the requests but only handle shell requests
go
func
()
{
for
req
:=
range
requests
{
switch
req
.
Type
{
case
"shell"
:
log
.
Infof
(
"payload: %s"
,
string
(
req
.
Payload
))
req
.
Reply
(
true
,
nil
)
default
:
log
.
Warnf
(
"unsupported request: %s"
,
req
.
Type
)
if
req
.
WantReply
{
req
.
Reply
(
false
,
nil
)
}
}
}
}()
}