source: code/trunk/ident.go@ 666

Last change on this file since 666 was 394, checked in by contact, 5 years ago

ident: remove leftover debug log

File size: 2.9 KB
RevLine 
[388]1package soju
2
3import (
4 "bufio"
5 "fmt"
6 "net"
7 "strconv"
8 "strings"
9 "sync"
10 "time"
11)
12
13var identdTimeout = 10 * time.Second
14
15type identKey struct {
16 remoteHost string
17 remotePort int
18 localPort int
19}
20
21func newIdentKey(remoteAddr, localAddr string) (*identKey, error) {
22 remoteHost, remotePort, err := splitHostPort(remoteAddr)
23 if err != nil {
24 return nil, err
25 }
26 _, localPort, err := splitHostPort(localAddr)
27 if err != nil {
28 return nil, err
29 }
30 return &identKey{
31 remoteHost: remoteHost,
32 remotePort: remotePort,
33 localPort: localPort,
34 }, nil
35}
36
37func splitHostPort(addr string) (host string, port int, err error) {
38 host, portStr, err := net.SplitHostPort(addr)
39 if err != nil {
40 return "", 0, err
41 }
42 port, err = strconv.Atoi(portStr)
43 return host, port, err
44}
45
46// Identd implements an ident server, as described in RFC 1413.
47type Identd struct {
48 entries map[identKey]string
49 lock sync.RWMutex
50}
51
52func NewIdentd() *Identd {
53 return &Identd{entries: make(map[identKey]string)}
54}
55
56func (s *Identd) Store(remoteAddr, localAddr, ident string) {
57 k, err := newIdentKey(remoteAddr, localAddr)
58 if err != nil {
59 return
60 }
61 s.lock.Lock()
62 s.entries[*k] = ident
63 s.lock.Unlock()
64}
65
66func (s *Identd) Delete(remoteAddr, localAddr string) {
67 k, err := newIdentKey(remoteAddr, localAddr)
68 if err != nil {
69 return
70 }
71 s.lock.Lock()
72 delete(s.entries, *k)
73 s.lock.Unlock()
74}
75
76func (s *Identd) Serve(ln net.Listener) error {
77 for {
78 conn, err := ln.Accept()
79 if err != nil {
80 return fmt.Errorf("failed to accept connection: %v", err)
81 }
82
83 go s.handle(conn)
84 }
85}
86
87func (s *Identd) handle(c net.Conn) {
88 defer c.Close()
89
90 remoteHost, _, err := net.SplitHostPort(c.RemoteAddr().String())
91 if err != nil {
92 return
93 }
94
95 scanner := bufio.NewScanner(c)
96
97 // We only read to read lines with two port numbers
98 var buf [512]byte
99 scanner.Buffer(buf[:], len(buf))
100
101 for {
102 c.SetDeadline(time.Now().Add(identdTimeout))
103 if !scanner.Scan() {
104 break
105 }
106 l := scanner.Text()
107
108 localPort, remotePort, err := parseIdentQuery(l)
109 if err != nil {
110 fmt.Fprintf(c, "%s : ERROR : INVALID-PORT\r\n", l)
111 break
112 }
113
114 k := identKey{
115 remoteHost: remoteHost,
116 remotePort: remotePort,
117 localPort: localPort,
118 }
119
120 s.lock.RLock()
121 ident := s.entries[k]
122 s.lock.RUnlock()
123
124 if ident == "" {
125 fmt.Fprintf(c, "%s : ERROR : NO-USER\r\n", l)
126 break
127 }
128
129 fmt.Fprintf(c, "%s : USERID : OTHER : %s\r\n", l, ident)
130 }
131}
132
133func parseIdentQuery(l string) (localPort, remotePort int, err error) {
134 parts := strings.SplitN(l, ",", 2)
135 if len(parts) != 2 {
136 return 0, 0, fmt.Errorf("expected two ports")
137 }
138 localStr, remoteStr := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
139 if localPort, err = strconv.Atoi(localStr); err != nil {
140 return 0, 0, err
141 }
142 if remotePort, err = strconv.Atoi(remoteStr); err != nil {
143 return 0, 0, err
144 }
145 if localPort <= 0 || remotePort <= 0 {
146 return 0, 0, fmt.Errorf("invalid port")
147 }
148 return localPort, remotePort, nil
149}
Note: See TracBrowser for help on using the repository browser.