-
Notifications
You must be signed in to change notification settings - Fork 0
/
register.go
142 lines (129 loc) · 3.87 KB
/
register.go
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright (c) 2011 The Grumble Authors
// The use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE-file.
package main
// This file handles public server list registration
import (
"bytes"
"crypto/sha1"
"crypto/tls"
"encoding/hex"
"encoding/xml"
"fmt"
"io/ioutil"
"net/http"
)
type Register struct {
XMLName xml.Name `xml:"server"`
Version string `xml:"version"`
Release string `xml:"release"`
Name string `xml:"name"`
Host string `xml:"host"`
Password string `xml:"password"`
Port int `xml:"port"`
URL string `xml:"url"`
Digest string `xml:"digest"`
Users int `xml:"users"`
Channels int `xml:"channels"`
Location string `xml:"location"`
}
const registerUrl = "https://publist-registration.mumble.info/v1/register"
// IsPublic Determines whether a server is public by checking whether the
// config values required for public registration are set.
//
// This function is used to determine whether or not to periodically
// contact the master server list and update this server's metadata.
func (server *Server) IsPublic() bool {
if server.cfg.Publish == false {
return false
}
if server.cfg.RegisterName == "" {
return false
}
//if server.cfg.RegisterHostname == "" {
// return false
//}
if server.cfg.AllowPing == false {
return false
}
if server.cfg.RegisterPassword == "" {
return false
}
if server.cfg.RegisterUrl == "" {
return false
}
return true
}
// RegisterPublicServer Perform a public server registration update.
//
// When a Mumble server connects to the master server
// for registration, it connects using its server certificate
// as a client certificate for authentication purposes.
func (server *Server) RegisterPublicServer() {
if !server.IsPublic() {
server.Println("register: Not registering server as it is not public.")
return
}
cert, _ := server.tlscfg.GetCertificate(nil)
// Fetch the server's certificates and put them in a tls.Config.
// We need the certificate chain to be able to use it in our client
// certificate chain to the registration server, and we also need to
// include a digest of the leaf certiifcate in the registration XML document
// we send off to the server.
config := &tls.Config{
Certificates: []tls.Certificate{*cert},
}
hasher := sha1.New()
// hasher.Write(config.Certificates[0].Certificate[0])
hasher.Write(cert.Certificate[0])
digest := hex.EncodeToString(hasher.Sum(nil))
// Render registration XML template
reg := Register{
Name: server.cfg.RegisterName,
Host: server.cfg.RegisterHostname,
Password: server.cfg.RegisterPassword,
URL: server.cfg.RegisterUrl,
Location: server.cfg.RegisterLocation,
Port: server.CurrentPort(),
Digest: digest,
Users: server.clients.Len(),
Channels: int(server.CountChannel()),
Version: verProtoverText,
Release: fmt.Sprintf("%s %s", verRelease, VERSION),
}
buf := bytes.NewBuffer(nil)
err := xml.NewEncoder(buf).Encode(reg)
if err != nil {
server.Printf("register: unable to marshal xml: %v", err)
return
}
// Post registration XML data to server asynchronously in its own goroutine
go func() {
tr := &http.Transport{
TLSClientConfig: config,
}
client := &http.Client{
Transport: tr,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
r, err := client.Post(registerUrl, "text/xml", buf)
if err != nil {
server.Printf("register: unable to post registration request: %v", err)
return
}
bodyBytes, err := ioutil.ReadAll(r.Body)
if err == nil {
registerMsg := string(bodyBytes)
if r.StatusCode == 200 {
server.Printf("register: %v", registerMsg)
} else {
server.Printf("register: (status %v) %v", r.StatusCode, registerMsg)
}
} else {
server.Printf("register: unable to read post response: %v", err)
return
}
}()
}