This commit is contained in:
kayos@tcp.direct 2021-09-28 14:08:24 -07:00
parent 729c3aee50
commit c236f43e92
27 changed files with 60 additions and 144 deletions

View File

@ -12,7 +12,7 @@ import (
"golang.org/x/crypto/ssh"
"git.tcp.direct/kayos/teletypewriter/set"
"git.tcp.direct/kayos/sh3lly/set"
)
// ErrNotWhitelisted Is the error returned when a key is checked that is not whitelisted,

View File

@ -3,7 +3,7 @@ package auth
import (
"github.com/rs/zerolog"
"git.tcp.direct/kayos/teletypewriter/config"
"git.tcp.direct/kayos/sh3lly/config"
)
var log zerolog.Logger

View File

@ -11,7 +11,7 @@ import (
"golang.org/x/crypto/bcrypt"
"golang.org/x/crypto/ssh"
"git.tcp.direct/kayos/teletypewriter/config"
"git.tcp.direct/kayos/sh3lly/config"
)
// RegisteredUser represents a user from our user system.
@ -63,9 +63,8 @@ type Authenticator interface {
// UserDB is our account database for passphrase authentication.
type UserDB struct {
Sessions *SessionManager
DB *bitcask.Bitcask
mu *sync.RWMutex
DB *bitcask.Bitcask
mu *sync.RWMutex
}
// AllowAnonymous determines if we allow anonymous connection to our server.
@ -98,7 +97,7 @@ func NewUserDB(path string) (db *UserDB, err error) {
if b, err = bitcask.Open(path); err != nil {
return
}
db = &UserDB{DB: b, mu: &sync.RWMutex{}, Sessions: NewSessionManager()}
db = &UserDB{DB: b, mu: &sync.RWMutex{}}
return
}
@ -137,6 +136,7 @@ func (users *UserDB) Register(user, pass string) (*RegisteredUser, error) {
return u, err
}
// AssignPublicKeyToUser attaches an SSH public key to the target registered user.
func (users *UserDB) AssignPublicKeyToUser(user *RegisteredUser, key ssh.PublicKey) error {
users.mu.Lock()
defer users.mu.Unlock()
@ -196,12 +196,13 @@ func (users *UserDB) KeyLogin(user string, pubkey ssh.PublicKey) error {
return errors.New("invalid key for user")
}
// UserExists checks for the existence of the given username in our database.
func (users *UserDB) UserExists(user string) bool {
_, err := users.GetUser(user)
return err == nil
}
// Sync synchronizes the in-memory admin map into our bitcask database
// Sync synchronizes the in-memory admin map into our bitcask database.
func (users *UserDB) Sync(user *RegisteredUser) error {
newuser, err := json.Marshal(user)
if err != nil {

View File

@ -1,80 +0,0 @@
package auth
import (
"errors"
"sync"
"git.tcp.direct/kayos/teletypewriter/chat/message"
)
// SessionManager keeps track of who's online.
type SessionManager struct {
Online map[*RegisteredUser]*message.User
userdb *UserDB
mu *sync.RWMutex
}
// NewSessionManager returns a session manager we use to track who is online.
func NewSessionManager() *SessionManager {
return &SessionManager{
Online: make(map[*RegisteredUser]*message.User),
mu: &sync.RWMutex{},
}
}
// IsOnline returns true if the given username is currently online.
func (sesh *SessionManager) IsOnline(username string) (u *RegisteredUser, ok bool) {
sesh.mu.Lock()
defer sesh.mu.Unlock()
var err error
u, err = sesh.userdb.GetUser(username)
if err != nil {
return &RegisteredUser{}, false
}
if _, ok = sesh.Online[u]; !ok {
u = &RegisteredUser{}
}
return
}
// SetOnline adds the given user to our active sessions map.
func (sesh *SessionManager) SetOnline(msguser *message.User) error {
sesh.mu.Lock()
defer sesh.mu.Unlock()
var u *RegisteredUser
var err error
if u, err = sesh.userdb.GetUser(msguser.Name()); err != nil {
return err
}
if _, ok := sesh.Online[u]; ok {
return errors.New("already logged in: " + u.Username)
}
sesh.Online[u] = msguser
log.Debug().Msgf("added to session: %s", u.Username)
return nil
}
// SetOffline removes the given user to our active sessions map and closes their connection.
func (sesh *SessionManager) SetOffline(msguser *message.User) error {
sesh.mu.Lock()
defer sesh.mu.Unlock()
var u *RegisteredUser
var err error
if u, err = sesh.userdb.GetUser(msguser.Name()); err != nil {
return err
}
if _, ok := sesh.Online[u]; ok {
return errors.New("already logged in: " + u.Username)
}
if _, ok := sesh.Online[u]; !ok {
return errors.New("not logged in: " + u.Username)
}
sesh.Online[u].Close()
delete(sesh.Online, u)
log.Debug().Msgf("removed from session: %s", u.Username)
return nil
}

View File

@ -7,7 +7,7 @@ import (
"golang.org/x/crypto/ssh"
"git.tcp.direct/kayos/teletypewriter/internal/sanitize"
"git.tcp.direct/kayos/sh3lly/internal/sanitize"
)
func (users *UserDB) keyboardInteractive(conn ssh.ConnMetadata, challenge ssh.KeyboardInteractiveChallenge) (*ssh.Permissions, error) {

View File

@ -9,9 +9,9 @@ import (
"strings"
"time"
"git.tcp.direct/kayos/teletypewriter/chat/message"
"git.tcp.direct/kayos/teletypewriter/internal/sanitize"
"git.tcp.direct/kayos/teletypewriter/set"
"git.tcp.direct/kayos/sh3lly/chat/message"
"git.tcp.direct/kayos/sh3lly/internal/sanitize"
"git.tcp.direct/kayos/sh3lly/set"
)
// ErrInvalidCommand is the error returned when an invalid command is issued.

View File

@ -5,7 +5,7 @@ import (
"sort"
"strings"
"git.tcp.direct/kayos/teletypewriter/chat/message"
"git.tcp.direct/kayos/sh3lly/chat/message"
)
type helpItem struct {

View File

@ -3,7 +3,7 @@ package chat
import (
"github.com/rs/zerolog"
"git.tcp.direct/kayos/teletypewriter/config"
"git.tcp.direct/kayos/sh3lly/config"
)
var log zerolog.Logger

View File

@ -7,8 +7,6 @@ type Identifier interface {
Name() string
}
// SimpleID is a simple Identifier implementation used for testing.
type SimpleID string

View File

@ -13,7 +13,7 @@ import (
"github.com/rs/zerolog/log"
"git.tcp.direct/kayos/teletypewriter/set"
"git.tcp.direct/kayos/sh3lly/set"
)
const messageBuffer = 5
@ -98,7 +98,7 @@ func (u *User) SetAway(msg string) {
func (u *User) SetGroup(grp string) {
u.mu.Lock()
defer u.mu.Unlock()
u.config.ZombieGrp=grp
u.config.ZombieGrp = grp
}
// GetAway returns if the user is away, when they went away, and the reason.

View File

@ -6,9 +6,9 @@ import (
"sort"
"sync"
"git.tcp.direct/kayos/teletypewriter/chat/message"
"git.tcp.direct/kayos/teletypewriter/internal/humantime"
"git.tcp.direct/kayos/teletypewriter/set"
"git.tcp.direct/kayos/sh3lly/chat/message"
"git.tcp.direct/kayos/sh3lly/internal/humantime"
"git.tcp.direct/kayos/sh3lly/set"
)
const historyLen = 20

View File

@ -12,12 +12,12 @@ import (
"golang.org/x/crypto/ssh"
"golang.org/x/term"
"git.tcp.direct/kayos/teletypewriter/auth"
"git.tcp.direct/kayos/teletypewriter/chat/message"
"git.tcp.direct/kayos/teletypewriter/config"
"git.tcp.direct/kayos/teletypewriter/host"
"git.tcp.direct/kayos/teletypewriter/shells"
"git.tcp.direct/kayos/teletypewriter/sshd"
"git.tcp.direct/kayos/sh3lly/auth"
"git.tcp.direct/kayos/sh3lly/chat/message"
"git.tcp.direct/kayos/sh3lly/config"
"git.tcp.direct/kayos/sh3lly/host"
"git.tcp.direct/kayos/sh3lly/shells"
"git.tcp.direct/kayos/sh3lly/sshd"
)
var log zerolog.Logger

View File

@ -107,8 +107,8 @@ func setDefaults() {
}
Opt["shells"] = map[string]interface{}{
"bind_addr": "192.168.69.5",
"bind_port": 4444,
"bind_addr": "192.168.69.5",
"bind_port": 4444,
}
Opt["database"] = map[string]interface{}{
@ -209,7 +209,7 @@ func processOpts() {
}
intOpt := map[string]*int{
"ssh.bind_port": &BindPort,
"ssh.bind_port": &BindPort,
"shells.bind_port": &ShellPort,
}

View File

@ -25,10 +25,10 @@ var (
// BindAddr is defined via our toml configuration file. It is the address that we listen on.
BindAddr string
// BindPort is defined via our toml configuration file. It is the port that we listen on.
BindPort int
BindPort int
AllowAnon bool
// KeyPath is where we store our RSA keys for the SSH server
KeyPath string
KeyPath string
SSHVersion string
)

4
go.mod
View File

@ -1,4 +1,4 @@
module git.tcp.direct/kayos/teletypewriter
module git.tcp.direct/kayos/sh3lly
go 1.17
@ -11,7 +11,7 @@ require (
github.com/spf13/viper v1.9.0
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20210925032602-92d5a993a665
golang.org/x/sys v0.0.0-20210927052749-1cf2251ac284
golang.org/x/term v0.0.0-20210916214954-140adaaadfaf
golang.org/x/text v0.3.7
)

4
go.sum
View File

@ -569,8 +569,8 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210925032602-92d5a993a665 h1:QOQNt6vCjMpXE7JSK5VvAzJC1byuN3FgTNSBwf+CJgI=
golang.org/x/sys v0.0.0-20210925032602-92d5a993a665/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927052749-1cf2251ac284 h1:lBPNCmq8u4zFP3huKCmUQ2Fx8kcY4X+O12UgGnyKsrg=
golang.org/x/sys v0.0.0-20210927052749-1cf2251ac284/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210916214954-140adaaadfaf h1:Ihq/mm/suC88gF8WFcVwk+OV6Tq+wyA1O0E5UEvDglI=
golang.org/x/term v0.0.0-20210916214954-140adaaadfaf/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=

View File

@ -11,12 +11,12 @@ import (
// "github.com/shazow/rateio"
"git.tcp.direct/kayos/teletypewriter/auth"
"git.tcp.direct/kayos/teletypewriter/chat"
"git.tcp.direct/kayos/teletypewriter/chat/message"
"git.tcp.direct/kayos/teletypewriter/identity"
"git.tcp.direct/kayos/teletypewriter/internal/humantime"
"git.tcp.direct/kayos/teletypewriter/sshd"
"git.tcp.direct/kayos/sh3lly/auth"
"git.tcp.direct/kayos/sh3lly/chat"
"git.tcp.direct/kayos/sh3lly/chat/message"
"git.tcp.direct/kayos/sh3lly/identity"
"git.tcp.direct/kayos/sh3lly/internal/humantime"
"git.tcp.direct/kayos/sh3lly/sshd"
)
const maxInputLength int = 1024
@ -432,7 +432,7 @@ func (h *Host) InitCommands(c *chat.Commands) {
return errors.New("user not found")
}
if target.Config().Zombie {
whois := "SHELL: "+target.Config().ZombieConn.RemoteAddr().String()
whois := "SHELL: " + target.Config().ZombieConn.RemoteAddr().String()
room.Send(message.NewSystemMsg(whois, msg.From()))
return nil
}
@ -584,7 +584,7 @@ func (h *Host) InitCommands(c *chat.Commands) {
}
var err error
var s string = strings.Join(args, " ")
var s = strings.Join(args, " ")
if s == "@" {
if h.GetMOTD == nil {

View File

@ -3,7 +3,7 @@ package host
import (
"github.com/rs/zerolog"
"git.tcp.direct/kayos/teletypewriter/config"
"git.tcp.direct/kayos/sh3lly/config"
)
var log zerolog.Logger

View File

@ -6,12 +6,12 @@ import (
"strings"
"time"
"git.tcp.direct/kayos/teletypewriter/auth"
"git.tcp.direct/kayos/teletypewriter/chat"
"git.tcp.direct/kayos/teletypewriter/chat/message"
"git.tcp.direct/kayos/teletypewriter/internal/humantime"
"git.tcp.direct/kayos/teletypewriter/internal/sanitize"
"git.tcp.direct/kayos/teletypewriter/sshd"
"git.tcp.direct/kayos/sh3lly/auth"
"git.tcp.direct/kayos/sh3lly/chat"
"git.tcp.direct/kayos/sh3lly/chat/message"
"git.tcp.direct/kayos/sh3lly/internal/humantime"
"git.tcp.direct/kayos/sh3lly/internal/sanitize"
"git.tcp.direct/kayos/sh3lly/sshd"
)
// Identity is a container for everything that identifies a client.

View File

@ -3,7 +3,7 @@ package identity
import (
"github.com/rs/zerolog"
"git.tcp.direct/kayos/teletypewriter/config"
"git.tcp.direct/kayos/sh3lly/config"
)
var log zerolog.Logger

View File

@ -1,4 +0,0 @@
Welcome to ssh-chat, enter /help for more.
🐛 Please enjoy our selection of bugs, but run your own server if you want to crash it: https://ssh.chat/issues
🍮 Sponsors get an emoji prefix: https://ssh.chat/sponsor
😌 Be nice and follow our Code of Conduct: https://ssh.chat/conduct

View File

@ -3,8 +3,8 @@ package shells
import (
"fmt"
"git.tcp.direct/kayos/teletypewriter/chat"
"git.tcp.direct/kayos/teletypewriter/chat/message"
"git.tcp.direct/kayos/sh3lly/chat"
"git.tcp.direct/kayos/sh3lly/chat/message"
)
func (c *Client) ID() string {

View File

@ -3,7 +3,7 @@ package shells
import (
"github.com/rs/zerolog"
"git.tcp.direct/kayos/teletypewriter/config"
"git.tcp.direct/kayos/sh3lly/config"
)
var log zerolog.Logger

View File

@ -5,7 +5,7 @@ import (
"net"
"sync"
"git.tcp.direct/kayos/teletypewriter/config"
"git.tcp.direct/kayos/sh3lly/config"
)
func Start() {

View File

@ -8,8 +8,8 @@ import (
"sync"
"time"
"git.tcp.direct/kayos/teletypewriter/chat"
"git.tcp.direct/kayos/teletypewriter/chat/message"
"git.tcp.direct/kayos/sh3lly/chat"
"git.tcp.direct/kayos/sh3lly/chat/message"
)
var srv *Server

View File

@ -3,7 +3,7 @@ package sshd
import (
"github.com/rs/zerolog"
"git.tcp.direct/kayos/teletypewriter/config"
"git.tcp.direct/kayos/sh3lly/config"
)
var log zerolog.Logger

View File

@ -7,8 +7,9 @@ import (
"sync"
"time"
"git.tcp.direct/kayos/teletypewriter/sshd/terminal"
"golang.org/x/crypto/ssh"
"git.tcp.direct/kayos/sh3lly/sshd/terminal"
)
var keepaliveInterval = time.Second * 30