|
@@ -6,8 +6,10 @@
|
6
|
6
|
package irc
|
7
|
7
|
|
8
|
8
|
import (
|
|
9
|
+ "errors"
|
9
|
10
|
"fmt"
|
10
|
11
|
"net"
|
|
12
|
+ "strings"
|
11
|
13
|
|
12
|
14
|
"github.com/oragono/oragono/irc/passwd"
|
13
|
15
|
|
|
@@ -18,23 +20,51 @@ import (
|
18
|
20
|
type webircConfig struct {
|
19
|
21
|
PasswordString string `yaml:"password"`
|
20
|
22
|
Password []byte `yaml:"password-bytes"`
|
|
23
|
+ Fingerprint string
|
21
|
24
|
Hosts []string
|
22
|
25
|
}
|
23
|
26
|
|
24
|
|
-// ProcessPassword populates our password.
|
25
|
|
-func (wc *webircConfig) ProcessPassword() error {
|
26
|
|
- password, error := passwd.DecodePasswordHash(wc.PasswordString)
|
27
|
|
- wc.Password = password
|
28
|
|
- return error
|
|
27
|
+// Populate fills out our password or fingerprint.
|
|
28
|
+func (wc *webircConfig) Populate() (err error) {
|
|
29
|
+ if wc.Fingerprint == "" && wc.PasswordString == "" {
|
|
30
|
+ return errors.New("Fingerprint or password needs to be specified")
|
|
31
|
+ }
|
|
32
|
+
|
|
33
|
+ if wc.PasswordString != "" {
|
|
34
|
+ var password []byte
|
|
35
|
+ password, err = passwd.DecodePasswordHash(wc.PasswordString)
|
|
36
|
+ wc.Password = password
|
|
37
|
+ }
|
|
38
|
+ return err
|
29
|
39
|
}
|
30
|
40
|
|
31
|
|
-// WEBIRC password gateway hostname ip
|
|
41
|
+// WEBIRC <password> <gateway> <hostname> <ip> [:flag1 flag2=x flag3]
|
32
|
42
|
func webircHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
33
|
43
|
// only allow unregistered clients to use this command
|
34
|
44
|
if client.registered {
|
35
|
45
|
return false
|
36
|
46
|
}
|
37
|
47
|
|
|
48
|
+ // process flags
|
|
49
|
+ var secure bool
|
|
50
|
+ if 4 < len(msg.Params) {
|
|
51
|
+ for _, x := range strings.Split(msg.Params[4], " ") {
|
|
52
|
+ // split into key=value
|
|
53
|
+ var key string
|
|
54
|
+ if strings.Contains(x, "=") {
|
|
55
|
+ y := strings.SplitN(x, "=", 2)
|
|
56
|
+ key, _ = y[0], y[1]
|
|
57
|
+ } else {
|
|
58
|
+ key = x
|
|
59
|
+ }
|
|
60
|
+
|
|
61
|
+ // only accept "tls" flag if the gateway's connection to us is secure as well
|
|
62
|
+ if strings.ToLower(key) == "tls" && client.flags[TLS] {
|
|
63
|
+ secure = true
|
|
64
|
+ }
|
|
65
|
+ }
|
|
66
|
+ }
|
|
67
|
+
|
38
|
68
|
clientAddress := utils.IPString(client.socket.conn.RemoteAddr())
|
39
|
69
|
clientHostname := client.hostname
|
40
|
70
|
server.configurableStateMutex.RLock()
|
|
@@ -42,13 +72,17 @@ func webircHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
42
|
72
|
for _, info := range server.webirc {
|
43
|
73
|
for _, address := range info.Hosts {
|
44
|
74
|
if clientHostname == address || clientAddress == address {
|
45
|
|
- // confirm password
|
|
75
|
+ // confirm password and/or fingerprint
|
46
|
76
|
givenPassword := msg.Params[0]
|
47
|
|
- if passwd.ComparePasswordString(info.Password, givenPassword) == nil {
|
48
|
|
- proxiedIP := msg.Params[3]
|
49
|
|
-
|
50
|
|
- return client.ApplyProxiedIP(proxiedIP)
|
|
77
|
+ if 0 < len(info.Password) && passwd.ComparePasswordString(info.Password, givenPassword) != nil {
|
|
78
|
+ continue
|
51
|
79
|
}
|
|
80
|
+ if 0 < len(info.Fingerprint) && client.certfp != info.Fingerprint {
|
|
81
|
+ continue
|
|
82
|
+ }
|
|
83
|
+
|
|
84
|
+ proxiedIP := msg.Params[3]
|
|
85
|
+ return client.ApplyProxiedIP(proxiedIP, secure)
|
52
|
86
|
}
|
53
|
87
|
}
|
54
|
88
|
}
|
|
@@ -73,7 +107,8 @@ func proxyHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
73
|
107
|
if clientHostname == address || clientAddress == address {
|
74
|
108
|
proxiedIP := msg.Params[1]
|
75
|
109
|
|
76
|
|
- return client.ApplyProxiedIP(proxiedIP)
|
|
110
|
+ // assume PROXY connections are always secure
|
|
111
|
+ return client.ApplyProxiedIP(proxiedIP, true)
|
77
|
112
|
}
|
78
|
113
|
}
|
79
|
114
|
client.Quit("PROXY command is not usable from your address")
|
|
@@ -81,7 +116,7 @@ func proxyHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
|
81
|
116
|
}
|
82
|
117
|
|
83
|
118
|
// ApplyProxiedIP applies the given IP to the client.
|
84
|
|
-func (client *Client) ApplyProxiedIP(proxiedIP string) (exiting bool) {
|
|
119
|
+func (client *Client) ApplyProxiedIP(proxiedIP string, tls bool) (exiting bool) {
|
85
|
120
|
// ensure IP is sane
|
86
|
121
|
parsedProxiedIP := net.ParseIP(proxiedIP)
|
87
|
122
|
if parsedProxiedIP == nil {
|
|
@@ -99,5 +134,14 @@ func (client *Client) ApplyProxiedIP(proxiedIP string) (exiting bool) {
|
99
|
134
|
client.proxiedIP = proxiedIP
|
100
|
135
|
client.rawHostname = utils.LookupHostname(proxiedIP)
|
101
|
136
|
client.hostname = client.rawHostname
|
|
137
|
+
|
|
138
|
+ // set tls info
|
|
139
|
+ client.certfp = ""
|
|
140
|
+ if tls {
|
|
141
|
+ client.flags[TLS] = true
|
|
142
|
+ } else {
|
|
143
|
+ delete(client.flags, TLS)
|
|
144
|
+ }
|
|
145
|
+
|
102
|
146
|
return false
|
103
|
147
|
}
|