mirror of
https://github.com/mumble-voip/grumble.git
synced 2025-12-19 21:59:59 -08:00
Add support for user authentication and also server password authentication
This commit is contained in:
parent
db518d7b16
commit
d24046b1b7
1 changed files with 53 additions and 10 deletions
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
|
"crypto/sha256"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
|
@ -175,8 +176,7 @@ func (server *Server) RootChannel() *Channel {
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set password as the new SuperUser password
|
func (server *Server) setConfigPassword(key, password string) {
|
||||||
func (server *Server) SetSuperUserPassword(password string) {
|
|
||||||
saltBytes := make([]byte, 24)
|
saltBytes := make([]byte, 24)
|
||||||
_, err := rand.Read(saltBytes)
|
_, err := rand.Read(saltBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -190,15 +190,23 @@ func (server *Server) SetSuperUserPassword(password string) {
|
||||||
digest := hex.EncodeToString(hasher.Sum(nil))
|
digest := hex.EncodeToString(hasher.Sum(nil))
|
||||||
|
|
||||||
// Could be racy, but shouldn't really matter...
|
// Could be racy, but shouldn't really matter...
|
||||||
key := "SuperUserPassword"
|
|
||||||
val := "sha1$" + salt + "$" + digest
|
val := "sha1$" + salt + "$" + digest
|
||||||
server.cfg.Set(key, val)
|
server.cfg.Set(key, val)
|
||||||
server.cfgUpdate <- &KeyValuePair{Key: key, Value: val}
|
server.cfgUpdate <- &KeyValuePair{Key: key, Value: val}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckSuperUserPassword checks whether password matches the set SuperUser password.
|
// Set password as the new SuperUser password
|
||||||
func (server *Server) CheckSuperUserPassword(password string) bool {
|
func (server *Server) SetSuperUserPassword(password string) {
|
||||||
parts := strings.Split(server.cfg.StringValue("SuperUserPassword"), "$")
|
server.setConfigPassword("SuperUserPassword", password)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set password as the new Server password
|
||||||
|
func (server *Server) SetServerPassword(password string) {
|
||||||
|
server.setConfigPassword("ServerPassword", password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) checkPassword(key, password string) bool {
|
||||||
|
parts := strings.Split(server.cfg.StringValue(key), "$")
|
||||||
if len(parts) != 3 {
|
if len(parts) != 3 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -236,6 +244,11 @@ func (server *Server) CheckSuperUserPassword(password string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CheckSuperUserPassword checks whether password matches the set SuperUser password.
|
||||||
|
func (server *Server) CheckSuperUserPassword(password string) bool {
|
||||||
|
return server.checkPassword("SuperUserPassword", password)
|
||||||
|
}
|
||||||
|
|
||||||
// Called by the server to initiate a new client connection.
|
// Called by the server to initiate a new client connection.
|
||||||
func (server *Server) handleIncomingClient(conn net.Conn) (err error) {
|
func (server *Server) handleIncomingClient(conn net.Conn) (err error) {
|
||||||
client := new(Client)
|
client := new(Client)
|
||||||
|
|
@ -439,6 +452,20 @@ func (server *Server) handlerLoop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func constantTimeEqual(s1, s2 string) bool {
|
||||||
|
one := sha256.Sum256([]byte(s1))
|
||||||
|
two := sha256.Sum256([]byte(s2))
|
||||||
|
return bytes.Compare(one[:], two[:]) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) hasServerPassword() bool {
|
||||||
|
return server.cfg.StringValue("ServerPassword") != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *Server) checkServerPassword(password string) bool {
|
||||||
|
return server.checkPassword("ServerPassword", password)
|
||||||
|
}
|
||||||
|
|
||||||
// Handle an Authenticate protobuf message. This is handled in a separate
|
// Handle an Authenticate protobuf message. This is handled in a separate
|
||||||
// goroutine to allow for remote authenticators that are slow to respond.
|
// goroutine to allow for remote authenticators that are slow to respond.
|
||||||
//
|
//
|
||||||
|
|
@ -498,12 +525,16 @@ func (server *Server) handleAuthenticate(client *Client, msg *Message) {
|
||||||
// First look up registration by name.
|
// First look up registration by name.
|
||||||
user, exists := server.UserNameMap[client.Username]
|
user, exists := server.UserNameMap[client.Username]
|
||||||
if exists {
|
if exists {
|
||||||
if client.HasCertificate() && user.CertHash == client.CertHash() {
|
if client.HasCertificate() {
|
||||||
client.user = user
|
if user.CertHash != client.CertHash() {
|
||||||
} else {
|
client.RejectAuth(mumbleproto.Reject_WrongUserPW, "Wrong certificate or password for existing user")
|
||||||
client.RejectAuth(mumbleproto.Reject_WrongUserPW, "Wrong certificate hash")
|
return
|
||||||
|
}
|
||||||
|
} else if *auth.Password != "" && user.Password != "" && !constantTimeEqual(*auth.Password, user.Password) {
|
||||||
|
client.RejectAuth(mumbleproto.Reject_WrongUserPW, "Wrong certificate or password for existing user")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
client.user = user
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name matching didn't do. Try matching by certificate.
|
// Name matching didn't do. Try matching by certificate.
|
||||||
|
|
@ -515,6 +546,18 @@ func (server *Server) handleAuthenticate(client *Client, msg *Message) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if client.user == nil && server.hasServerPassword() {
|
||||||
|
if auth.Password == nil {
|
||||||
|
client.RejectAuth(mumbleproto.Reject_WrongServerPW, "Invalid server password")
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
if !server.checkServerPassword(*auth.Password) {
|
||||||
|
client.RejectAuth(mumbleproto.Reject_WrongServerPW, "Invalid server password")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Setup the cryptstate for the client.
|
// Setup the cryptstate for the client.
|
||||||
err = client.crypt.GenerateKey(client.CryptoMode)
|
err = client.crypt.GenerateKey(client.CryptoMode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue