Add identd

This commit is contained in:
Ken-Håvard Lieng 2020-06-16 11:26:07 +02:00
parent 67fe5d263d
commit e0d2243248
9 changed files with 140 additions and 6 deletions

View File

@ -112,6 +112,7 @@ func init() {
viper.BindPFlags(rootCmd.PersistentFlags())
viper.BindPFlags(rootCmd.Flags())
viper.SetDefault("identd", true)
viper.SetDefault("auto_ctcp", true)
viper.SetDefault("verify_certificates", true)

View File

@ -1,6 +1,8 @@
# IP address to listen on, leave empty to listen on anything
address = ""
port = 80
# Run ident daemon on port 113
identd = true
# Hex encode the users IP and use it as the ident
hexIP = false
# Automatically reply to common CTCP messages

View File

@ -12,6 +12,7 @@ type Config struct {
Address string
Port string
Dev bool
Identd bool
HexIP bool
AutoCTCP bool `mapstructure:"auto_ctcp"`
VerifyCertificates bool `mapstructure:"verify_certificates"`

87
pkg/ident/server.go Normal file
View File

@ -0,0 +1,87 @@
package ident
import (
"bufio"
"fmt"
"net"
"strings"
"sync"
)
var (
DefaultAddr = ":113"
)
type Server struct {
Addr string
idents map[string]string
listener net.Listener
lock sync.Mutex
}
func NewServer() *Server {
return &Server{
idents: map[string]string{},
}
}
func (s *Server) Listen() error {
var err error
addr := s.Addr
if addr == "" {
addr = DefaultAddr
}
s.listener, err = net.Listen("tcp", addr)
if err != nil {
return err
}
defer s.listener.Close()
for {
conn, err := s.listener.Accept()
if err != nil {
return err
}
go s.handle(conn)
}
}
func (s *Server) Stop() error {
return s.listener.Close()
}
func (s *Server) Add(local, remote, ident string) {
s.lock.Lock()
s.idents[local+","+remote] = ident
s.lock.Unlock()
}
func (s *Server) Remove(local, remote string) {
s.lock.Lock()
delete(s.idents, local+","+remote)
s.lock.Unlock()
}
func (s *Server) handle(conn net.Conn) {
defer conn.Close()
scan := bufio.NewScanner(conn)
if !scan.Scan() {
return
}
line := scan.Text()
ports := strings.ReplaceAll(line, " ", "")
s.lock.Lock()
ident, ok := s.idents[ports]
s.lock.Unlock()
if ok {
conn.Write([]byte(fmt.Sprintf("%s : USERID : Dispatch : %s\r\n", line, ident)))
}
}

View File

@ -195,6 +195,19 @@ func (c *Client) Host() string {
return c.Config.Host
}
func (c *Client) LocalPort() string {
c.lock.Lock()
defer c.lock.Unlock()
if c.conn != nil {
_, local, err := net.SplitHostPort(c.conn.LocalAddr().String())
if err == nil {
return local
}
}
return ""
}
func (c *Client) MOTD() []string {
return c.state.getMOTD()
}

View File

@ -22,7 +22,6 @@ type Dialer interface {
}
func (c *Client) Connect() {
c.connChange(false, nil)
go c.run()
}
@ -147,7 +146,7 @@ func (c *Client) connect() error {
c.scan = bufio.NewScanner(c.conn)
c.scan.Buffer(c.recvBuf, cap(c.recvBuf))
c.register()
go c.register()
c.sendRecv.Add(1)
go c.recv()
@ -185,7 +184,7 @@ func (c *Client) recv() {
return
default:
c.connChange(false, nil)
c.connChange(false, c.scan.Err())
close(c.reconnect)
return
}
@ -198,8 +197,8 @@ func (c *Client) recv() {
msg := ParseMessage(string(b))
if msg == nil {
close(c.quit)
c.connChange(false, ErrBadProtocol)
close(c.quit)
return
}

View File

@ -46,6 +46,8 @@ func newIRCHandler(client *irc.Client, state *State) *ircHandler {
func (i *ircHandler) run() {
var lastConnErr error
var localPort string
for {
select {
case msg, ok := <-i.client.Messages:
@ -57,6 +59,16 @@ func (i *ircHandler) run() {
i.dispatchMessage(msg)
case state := <-i.client.ConnectionChanged:
if identd := i.state.srv.identd; identd != nil {
if state.Connected {
if localPort = i.client.LocalPort(); localPort != "" {
identd.Add(localPort, i.client.Config.Port, i.client.Config.Username)
}
} else {
identd.Remove(localPort, i.client.Config.Port)
}
}
i.state.sendJSON("connection_update", newConnectionUpdate(i.client.Host(), state))
if network, ok := i.state.network(i.client.Host()); ok {
@ -297,6 +309,16 @@ func (i *ircHandler) info(msg *irc.Message) {
i.client.List()
}
if identd := i.state.srv.identd; identd != nil {
if localPort := i.client.LocalPort(); localPort != "" {
identd.Remove(localPort, i.client.Config.Port)
}
}
if network, ok := i.state.network(i.client.Host()); ok {
network.SetNick(msg.Params[0])
}
go i.state.user.SetNick(msg.Params[0], i.client.Host())
}

View File

@ -56,7 +56,7 @@ func dispatchMessageMulti(msg *irc.Message) chan WSResponse {
Username: "user",
Host: "host.com",
})
s := NewState(user, nil)
s := NewState(user, &Dispatch{})
newIRCHandler(c, s).dispatchMessage(msg)

View File

@ -11,6 +11,7 @@ import (
"github.com/gorilla/websocket"
"github.com/khlieng/dispatch/config"
"github.com/khlieng/dispatch/pkg/https"
"github.com/khlieng/dispatch/pkg/ident"
"github.com/khlieng/dispatch/pkg/session"
"github.com/khlieng/dispatch/storage"
)
@ -24,6 +25,7 @@ type Dispatch struct {
cfg *config.Config
upgrader websocket.Upgrader
states *stateStore
identd *ident.Server
lock sync.Mutex
}
@ -47,17 +49,24 @@ func (d *Dispatch) SetConfig(cfg *config.Config) {
}
func (d *Dispatch) Run() {
cfg := d.Config()
d.upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
if d.Config().Dev {
if cfg.Dev {
d.upgrader.CheckOrigin = func(r *http.Request) bool {
return true
}
}
if cfg.Identd {
d.identd = ident.NewServer()
go d.identd.Listen()
}
session.CookieName = "dispatch"
d.states = newStateStore(d.SessionStore)