summaryrefslogtreecommitdiff
path: root/webircgateway/pkg/identd
diff options
context:
space:
mode:
Diffstat (limited to 'webircgateway/pkg/identd')
-rw-r--r--webircgateway/pkg/identd/identd.go86
-rw-r--r--webircgateway/pkg/identd/rpcclient.go59
2 files changed, 145 insertions, 0 deletions
diff --git a/webircgateway/pkg/identd/identd.go b/webircgateway/pkg/identd/identd.go
new file mode 100644
index 0000000..9a84d76
--- /dev/null
+++ b/webircgateway/pkg/identd/identd.go
@@ -0,0 +1,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)
+ }
+}
diff --git a/webircgateway/pkg/identd/rpcclient.go b/webircgateway/pkg/identd/rpcclient.go
new file mode 100644
index 0000000..37aec3e
--- /dev/null
+++ b/webircgateway/pkg/identd/rpcclient.go
@@ -0,0 +1,59 @@
+package identd
+
+import "net"
+import "fmt"
+import "time"
+
+func MakeRpcClient(appName string) *RpcClient {
+ return &RpcClient{AppName: appName}
+}
+
+type RpcClient struct {
+ AppName string
+ Conn *net.Conn
+}
+
+func (rpc *RpcClient) ConnectAndReconnect(serverAddress string) {
+ for {
+ if rpc.Conn == nil {
+ println("Connecting to identd RPC...")
+ rpc.Connect(serverAddress)
+ }
+
+ time.Sleep(time.Second * 3)
+ }
+}
+
+func (rpc *RpcClient) Connect(serverAddress string) error {
+ conn, err := net.Dial("tcp", serverAddress)
+ if err != nil {
+ return err
+ }
+
+ rpc.Conn = &conn
+ rpc.Write("id " + rpc.AppName)
+
+ return nil
+}
+
+func (rpc *RpcClient) Write(line string) error {
+ if rpc.Conn == nil {
+ return fmt.Errorf("not connected")
+ }
+
+ conn := *rpc.Conn
+ _, err := conn.Write([]byte(line + "\n"))
+ if err != nil {
+ rpc.Conn = nil
+ conn.Close()
+ }
+ return err
+}
+
+func (rpc *RpcClient) AddIdent(lport int, rport int, username string, iface string) {
+ rpc.Write(fmt.Sprintf("add %s %d %d %s", username, lport, rport, iface))
+}
+
+func (rpc *RpcClient) RemoveIdent(lport int, rport int, username string, iface string) {
+ rpc.Write(fmt.Sprintf("del %d %d %s", lport, rport, iface))
+}