diff --git a/cmd/serve.go b/cmd/serve.go index f26f472f..81d2cdd0 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -18,9 +18,9 @@ func init() { configs := []config.Config{ neko.Service.Configs.Capture, - neko.Service.Configs.Server, neko.Service.Configs.WebRTC, - neko.Service.Configs.WebSocket, + neko.Service.Configs.Session, + neko.Service.Configs.Server, } cobra.OnInitialize(func() { diff --git a/internal/config/server.go b/internal/config/server.go index 2f2bc39c..eab02938 100644 --- a/internal/config/server.go +++ b/internal/config/server.go @@ -10,6 +10,7 @@ type Server struct { Key string Bind string Static string + //Proxy bool UserToken string AdminToken string } @@ -35,6 +36,11 @@ func (Server) Init(cmd *cobra.Command) error { return err } + //cmd.PersistentFlags().Bool("proxy", false, "allow reverse proxies") + //if err := viper.BindPFlag("proxy", cmd.PersistentFlags().Lookup("proxy")); err != nil { + // return err + //} + cmd.PersistentFlags().String("user_token", "user_secret", "JWT token for users") if err := viper.BindPFlag("user_token", cmd.PersistentFlags().Lookup("user_token")); err != nil { return err @@ -53,6 +59,7 @@ func (s *Server) Set() { s.Key = viper.GetString("key") s.Bind = viper.GetString("bind") s.Static = viper.GetString("static") + //s.Proxy = viper.GetBool("proxy") s.UserToken = viper.GetString("user_token") s.AdminToken = viper.GetString("admin_token") } diff --git a/internal/config/websocket.go b/internal/config/session.go similarity index 66% rename from internal/config/websocket.go rename to internal/config/session.go index 099f34bd..2b06895f 100644 --- a/internal/config/websocket.go +++ b/internal/config/session.go @@ -5,13 +5,12 @@ import ( "github.com/spf13/viper" ) -type WebSocket struct { +type Session struct { Password string AdminPassword string - Proxy bool } -func (WebSocket) Init(cmd *cobra.Command) error { +func (Session) Init(cmd *cobra.Command) error { cmd.PersistentFlags().String("password", "neko", "password for connecting to stream") if err := viper.BindPFlag("password", cmd.PersistentFlags().Lookup("password")); err != nil { return err @@ -22,16 +21,10 @@ func (WebSocket) Init(cmd *cobra.Command) error { return err } - cmd.PersistentFlags().Bool("proxy", false, "enable reverse proxy mode") - if err := viper.BindPFlag("proxy", cmd.PersistentFlags().Lookup("proxy")); err != nil { - return err - } - return nil } -func (s *WebSocket) Set() { +func (s *Session) Set() { s.Password = viper.GetString("password") s.AdminPassword = viper.GetString("password_admin") - s.Proxy = viper.GetBool("proxy") } diff --git a/internal/session/auth.go b/internal/session/auth.go new file mode 100644 index 00000000..9fbb7f95 --- /dev/null +++ b/internal/session/auth.go @@ -0,0 +1,37 @@ +package session + +import ( + "fmt" + "net/http" + + "demodesk/neko/internal/utils" +) + +// TODO: Refactor +func (manager *SessionManagerCtx) Authenticate(r *http.Request) (string, string, bool, error) { + ip := r.RemoteAddr + + //if ws.conf.Proxy { + // ip = utils.ReadUserIP(r) + //} + + id, err := utils.NewUID(32) + if err != nil { + return "", ip, false, err + } + + passwords, ok := r.URL.Query()["password"] + if !ok || len(passwords[0]) < 1 { + return "", ip, false, fmt.Errorf("no password provided") + } + + if passwords[0] == manager.config.AdminPassword { + return id, ip, true, nil + } + + if passwords[0] == manager.config.Password { + return id, ip, false, nil + } + + return "", ip, false, fmt.Errorf("invalid password: %s", passwords[0]) +} diff --git a/internal/session/manager.go b/internal/session/manager.go index 9a882c37..6bb113d9 100644 --- a/internal/session/manager.go +++ b/internal/session/manager.go @@ -6,14 +6,16 @@ import ( "github.com/rs/zerolog/log" "demodesk/neko/internal/types" + "demodesk/neko/internal/config" "demodesk/neko/internal/utils" ) -func New(capture types.CaptureManager) *SessionManagerCtx { +func New(capture types.CaptureManager, config *config.Session) *SessionManagerCtx { return &SessionManagerCtx{ logger: log.With().Str("module", "session").Logger(), host: nil, capture: capture, + config: config, members: make(map[string]*SessionCtx), emmiter: events.New(), } @@ -23,6 +25,7 @@ type SessionManagerCtx struct { logger zerolog.Logger host types.Session capture types.CaptureManager + config *config.Session members map[string]*SessionCtx emmiter events.EventEmmiter } diff --git a/internal/types/session.go b/internal/types/session.go index 136ebb30..e12e53bd 100644 --- a/internal/types/session.go +++ b/internal/types/session.go @@ -1,5 +1,7 @@ package types +import "net/http" + type Session interface { ID() string Name() string @@ -38,4 +40,7 @@ type SessionManager interface { OnDestroy(listener func(id string)) OnCreated(listener func(session Session)) OnConnected(listener func(session Session)) + + // auth + Authenticate(r *http.Request) (string, string, bool, error) } diff --git a/internal/websocket/manager.go b/internal/websocket/manager.go index 80f8d8ee..bef21bb4 100644 --- a/internal/websocket/manager.go +++ b/internal/websocket/manager.go @@ -1,7 +1,6 @@ package websocket import ( - "fmt" "net/http" "time" @@ -14,8 +13,6 @@ import ( "demodesk/neko/internal/types/message" "demodesk/neko/internal/types" - "demodesk/neko/internal/config" - "demodesk/neko/internal/utils" ) func New( @@ -23,13 +20,11 @@ func New( desktop types.DesktopManager, capture types.CaptureManager, webrtc types.WebRTCManager, - conf *config.WebSocket, ) *WebSocketManagerCtx { logger := log.With().Str("module", "websocket").Logger() return &WebSocketManagerCtx{ logger: logger, - conf: conf, sessions: sessions, desktop: desktop, upgrader: websocket.Upgrader{ @@ -49,7 +44,6 @@ type WebSocketManagerCtx struct { upgrader websocket.Upgrader sessions types.SessionManager desktop types.DesktopManager - conf *config.WebSocket handler *handler.MessageHandlerCtx shutdown chan bool } @@ -80,8 +74,10 @@ func (ws *WebSocketManagerCtx) Start() { }) go func() { + ws.logger.Info().Msg("clipboard loop started") + defer func() { - ws.logger.Info().Msg("shutdown") + ws.logger.Info().Msg("clipboard loop stopped") }() current := ws.desktop.ReadClipboard() @@ -131,7 +127,7 @@ func (ws *WebSocketManagerCtx) Upgrade(w http.ResponseWriter, r *http.Request) e return err } - id, ip, admin, err := ws.authenticate(r) + id, ip, admin, err := ws.sessions.Authenticate(r) if err != nil { ws.logger.Warn().Err(err).Msg("authentication failed") @@ -186,35 +182,6 @@ func (ws *WebSocketManagerCtx) Upgrade(w http.ResponseWriter, r *http.Request) e return nil } -// TODO: Refactor -func (ws *WebSocketManagerCtx) authenticate(r *http.Request) (string, string, bool, error) { - ip := r.RemoteAddr - - if ws.conf.Proxy { - ip = utils.ReadUserIP(r) - } - - id, err := utils.NewUID(32) - if err != nil { - return "", ip, false, err - } - - passwords, ok := r.URL.Query()["password"] - if !ok || len(passwords[0]) < 1 { - return "", ip, false, fmt.Errorf("no password provided") - } - - if passwords[0] == ws.conf.AdminPassword { - return id, ip, true, nil - } - - if passwords[0] == ws.conf.Password { - return id, ip, false, nil - } - - return "", ip, false, fmt.Errorf("invalid password: %s", passwords[0]) -} - func (ws *WebSocketManagerCtx) handle(connection *websocket.Conn, id string) { bytes := make(chan []byte) cancel := make(chan struct{}) diff --git a/neko.go b/neko.go index 1ba5117b..c91574dd 100644 --- a/neko.go +++ b/neko.go @@ -64,8 +64,8 @@ func init() { Root: &config.Root{}, Capture: &config.Capture{}, WebRTC: &config.WebRTC{}, + Session: &config.Session{}, Server: &config.Server{}, - WebSocket: &config.WebSocket{}, }, } } @@ -103,8 +103,8 @@ type Configs struct { Root *config.Root Capture *config.Capture WebRTC *config.WebRTC + Session *config.Session Server *config.Server - WebSocket *config.WebSocket } type Neko struct { @@ -146,6 +146,7 @@ func (neko *Neko) Start() { neko.sessionManager = session.New( neko.captureManager, + neko.Configs.Session, ) neko.webSocketManager = websocket.New( @@ -153,7 +154,6 @@ func (neko *Neko) Start() { neko.desktopManager, neko.captureManager, neko.webRTCManager, - neko.Configs.WebSocket, ) neko.webSocketManager.Start()