Bind identd to config address, set read/write deadlines in ident.Server, only reply to ident queries where the remote hosts match

This commit is contained in:
Ken-Håvard Lieng 2020-06-17 03:19:20 +02:00
parent 15ee5ce1c9
commit 04e6e8c7a2
4 changed files with 92 additions and 28 deletions

View File

@ -6,23 +6,37 @@ import (
"net" "net"
"strings" "strings"
"sync" "sync"
"time"
) )
var ( var (
// DefaultAddr is the address a Server listens on when no Addr is specified
DefaultAddr = ":113" DefaultAddr = ":113"
// DefaultTimeout is the the time a Server will wait before failing
// reads and writes if no Timeout is specified
DefaultTimeout = 5 * time.Second
) )
// Server implements the server-side of the Ident protocol
type Server struct { type Server struct {
// Addr is the host:port address to listen on
Addr string Addr string
// Timeout is the time to wait before failing reads and writes
Timeout time.Duration
idents map[string]string entries map[string]entry
listener net.Listener listener net.Listener
lock sync.Mutex lock sync.Mutex
} }
type entry struct {
remoteHost string
ident string
}
func NewServer() *Server { func NewServer() *Server {
return &Server{ return &Server{
idents: map[string]string{}, entries: map[string]entry{},
} }
} }
@ -54,35 +68,77 @@ func (s *Server) Stop() error {
return s.listener.Close() return s.listener.Close()
} }
func (s *Server) Add(local, remote, ident string) { func (s *Server) Add(local, remote net.Addr, ident string) {
if local == nil || remote == nil {
return
}
_, localPort, err := net.SplitHostPort(local.String())
if err != nil {
return
}
remoteHost, remotePort, err := net.SplitHostPort(remote.String())
if err != nil {
return
}
s.lock.Lock() s.lock.Lock()
s.idents[local+","+remote] = ident s.entries[localPort+","+remotePort] = entry{
remoteHost: remoteHost,
ident: ident,
}
s.lock.Unlock() s.lock.Unlock()
} }
func (s *Server) Remove(local, remote string) { func (s *Server) Remove(local, remote net.Addr) {
if local == nil || remote == nil {
return
}
_, localPort, err := net.SplitHostPort(local.String())
if err != nil {
return
}
_, remotePort, err := net.SplitHostPort(remote.String())
if err != nil {
return
}
s.lock.Lock() s.lock.Lock()
delete(s.idents, local+","+remote) delete(s.entries, localPort+","+remotePort)
s.lock.Unlock() s.lock.Unlock()
} }
func (s *Server) handle(conn net.Conn) { func (s *Server) handle(conn net.Conn) {
defer conn.Close() defer conn.Close()
timeout := s.Timeout
if timeout == 0 {
timeout = DefaultTimeout
}
scan := bufio.NewScanner(conn) scan := bufio.NewScanner(conn)
scan.Buffer(make([]byte, 32), 32) scan.Buffer(make([]byte, 32), 32)
conn.SetReadDeadline(time.Now().Add(timeout))
if !scan.Scan() { if !scan.Scan() {
return return
} }
query := scan.Text()
line := scan.Text()
ports := strings.ReplaceAll(line, " ", "")
s.lock.Lock() s.lock.Lock()
ident, ok := s.idents[ports] entry, ok := s.entries[strings.ReplaceAll(query, " ", "")]
s.lock.Unlock() s.lock.Unlock()
if ok { if ok {
conn.Write([]byte(fmt.Sprintf("%s : USERID : Dispatch : %s\r\n", line, ident))) remoteHost, _, err := net.SplitHostPort(conn.RemoteAddr().String())
if err != nil || remoteHost != entry.remoteHost {
return
}
conn.SetWriteDeadline(time.Now().Add(timeout))
conn.Write([]byte(fmt.Sprintf("%s : USERID : Dispatch : %s\r\n", query, entry.ident)))
} }
} }

View File

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

View File

@ -3,6 +3,7 @@ package server
import ( import (
"fmt" "fmt"
"log" "log"
"net"
"os" "os"
"strconv" "strconv"
"strings" "strings"
@ -46,7 +47,8 @@ func newIRCHandler(client *irc.Client, state *State) *ircHandler {
func (i *ircHandler) run() { func (i *ircHandler) run() {
var lastConnErr error var lastConnErr error
var localPort string var localAddr net.Addr
var remoteAddr net.Addr
for { for {
select { select {
@ -61,11 +63,10 @@ func (i *ircHandler) run() {
case state := <-i.client.ConnectionChanged: case state := <-i.client.ConnectionChanged:
if identd := i.state.srv.identd; identd != nil { if identd := i.state.srv.identd; identd != nil {
if state.Connected { if state.Connected {
if localPort = i.client.LocalPort(); localPort != "" { localAddr, remoteAddr = i.client.LocalAddr(), i.client.RemoteAddr()
identd.Add(localPort, i.client.Config.Port, i.client.Config.Username) identd.Add(localAddr, remoteAddr, i.client.Config.Username)
}
} else { } else {
identd.Remove(localPort, i.client.Config.Port) identd.Remove(localAddr, remoteAddr)
} }
} }
@ -310,9 +311,7 @@ func (i *ircHandler) info(msg *irc.Message) {
} }
if identd := i.state.srv.identd; identd != nil { if identd := i.state.srv.identd; identd != nil {
if localPort := i.client.LocalPort(); localPort != "" { identd.Remove(i.client.LocalAddr(), i.client.RemoteAddr())
identd.Remove(localPort, i.client.Config.Port)
}
} }
if network, ok := i.state.network(i.client.Host()); ok { if network, ok := i.state.network(i.client.Host()); ok {

View File

@ -2,6 +2,7 @@ package server
import ( import (
"log" "log"
"net"
"net/http" "net/http"
"os" "os"
"strconv" "strconv"
@ -64,6 +65,7 @@ func (d *Dispatch) Run() {
if cfg.Identd { if cfg.Identd {
d.identd = ident.NewServer() d.identd = ident.NewServer()
d.identd.Addr = net.JoinHostPort(cfg.Address, "113")
go d.identd.Listen() go d.identd.Listen()
} }
@ -74,7 +76,7 @@ func (d *Dispatch) Run() {
d.loadUsers() d.loadUsers()
d.initFileServer() d.initFileServer()
d.startHTTP() d.serveHTTP()
} }
func (d *Dispatch) loadUsers() { func (d *Dispatch) loadUsers() {
@ -119,12 +121,12 @@ func (d *Dispatch) loadUser(user *storage.User) {
} }
} }
func (d *Dispatch) startHTTP() { func (d *Dispatch) serveHTTP() {
cfg := d.Config() cfg := d.Config()
port := cfg.Port port := cfg.Port
if cfg.Dev { if cfg.Dev {
// The node dev network will proxy index page requests and // The node dev server will proxy index page requests and
// websocket connections to this port // websocket connections to this port
port = "1337" port = "1337"
} }