summaryrefslogtreecommitdiff
path: root/deprecated-webircgateway/pkg/identd/identd.go
blob: 9a84d76939cccf1c78cdc42c70f7130eef3051f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package identd

import (
	"fmt"
	"net"
	"net/textproto"
	"strings"
	"sync"
)

// Server - An IdentD server
type Server struct {
	Entries     map[string]string
	EntriesLock sync.Mutex
}

// NewIdentdServer - Create a new IdentdServer instance
func NewIdentdServer() Server {
	return Server{
		Entries: make(map[string]string),
	}
}

// AddIdent - Add an ident to be looked up
func (i *Server) AddIdent(localPort, remotePort int, ident string, iface string) {
	i.EntriesLock.Lock()
	i.Entries[fmt.Sprintf("%d-%d", localPort, remotePort)] = ident
	i.EntriesLock.Unlock()
}

// RemoveIdent - Remove an ident from being looked up
func (i *Server) RemoveIdent(localPort, remotePort int, iface string) {
	i.EntriesLock.Lock()
	delete(i.Entries, fmt.Sprintf("%d-%d", localPort, remotePort))
	i.EntriesLock.Unlock()
}

// Run - Start listening for ident lookups
func (i *Server) Run() error {
	serv, err := net.Listen("tcp", ":113")
	if err != nil {
		return err
	}

	go i.ListenForRequests(&serv)
	return nil
}

// ListenForRequests - Listen on a net.Listener for ident lookups
func (i *Server) ListenForRequests(serverSocket *net.Listener) {
	for {
		serv := *serverSocket
		client, err := serv.Accept()
		if err != nil {
			break
		}

		go func(conn net.Conn) {
			tc := textproto.NewConn(conn)

			line, err := tc.ReadLine()
			if err != nil {
				conn.Close()
				return
			}

			// Remove all spaces, some servers like to send "%d , %d" but the spec examples use "%d, %d"
			line = strings.ReplaceAll(line, " ", "")

			var localPort, remotePort int
			fmt.Sscanf(line, "%d,%d", &localPort, &remotePort)
			if localPort > 0 && remotePort > 0 {
				i.EntriesLock.Lock()
				ident, ok := i.Entries[fmt.Sprintf("%d-%d", localPort, remotePort)]
				i.EntriesLock.Unlock()
				if !ok {
					fmt.Fprintf(conn, "%d, %d : ERROR : NO-USER\r\n", localPort, remotePort)
				} else {
					fmt.Fprintf(conn, "%d, %d : USERID : UNIX : %s\r\n", localPort, remotePort, ident)
				}
			}

			conn.Close()
		}(client)
	}
}