1
0
Fork 0
forked from External/grumble

Enforce certhash-based bans and add strong certificate checking (non-working for now, crypto/tls doesn't verify client certificates)

This commit is contained in:
Mikkel Krautz 2011-11-12 23:55:33 +01:00
parent 0b1794f9b5
commit 1240fe3eb6
3 changed files with 55 additions and 20 deletions

View file

@ -7,6 +7,7 @@ package main
import (
"bufio"
"bytes"
"crypto/tls"
"encoding/binary"
"goprotobuf.googlecode.com/hg/proto"
"grumble/blobstore"
@ -125,6 +126,15 @@ func (client *Client) ShownName() string {
return client.Username
}
// Check whether the client's certificate is
// verified.
func (client *Client) IsVerified() bool {
tlsconn := client.conn.(*tls.Conn)
state := tlsconn.ConnectionState()
client.Printf("%v", state.VerifiedChains)
return len(state.VerifiedChains) > 0
}
// Log a panic and disconnect the client.
func (client *Client) Panic(v ...interface{}) {
client.Print(v)

View file

@ -1327,7 +1327,7 @@ func (server *Server) handleUserStatsMessage(client *Client, msg *Message) {
for i := len(state.PeerCertificates) - 1; i >= 0; i-- {
stats.Certificates = append(stats.Certificates, state.PeerCertificates[i].Raw)
}
// fixme(mkrautz): strong certificate checking
stats.StrongCertificate = proto.Bool(target.IsVerified())
}
}

View file

@ -227,7 +227,7 @@ func (server *Server) CheckSuperUserPassword(password string) bool {
}
// Called by the server to initiate a new client connection.
func (server *Server) NewClient(conn net.Conn) (err error) {
func (server *Server) handleIncomingClient(conn net.Conn) (err error) {
client := new(Client)
addr := conn.RemoteAddr()
if addr == nil {
@ -253,6 +253,30 @@ func (server *Server) NewClient(conn net.Conn) (err error) {
client.user = nil
// Extract user's cert hash
tlsconn := client.conn.(*tls.Conn)
err = tlsconn.Handshake()
if err != nil {
client.Printf("TLS handshake failed: %v", err)
client.Disconnect()
return
}
state := tlsconn.ConnectionState()
if len(state.PeerCertificates) > 0 {
hash := sha1.New()
hash.Write(state.PeerCertificates[0].Raw)
sum := hash.Sum()
client.CertHash = hex.EncodeToString(sum)
}
// Check whether the client's cert hash is banned
if server.IsCertHashBanned(client.CertHash) {
client.Printf("Certificate hash is banned")
client.Disconnect()
return
}
go client.receiver()
go client.udpreceiver()
@ -434,26 +458,13 @@ func (server *Server) handleAuthenticate(client *Client, msg *Message) {
client.Username = *auth.Username
// Extract certhash
tlsconn, ok := client.conn.(*tls.Conn)
if !ok {
client.Panic("Invalid connection")
return
}
state := tlsconn.ConnectionState()
if len(state.PeerCertificates) > 0 {
hash := sha1.New()
hash.Write(state.PeerCertificates[0].Raw)
sum := hash.Sum()
client.CertHash = hex.EncodeToString(sum)
}
if client.Username == "SuperUser" {
if auth.Password == nil {
client.RejectAuth(mumbleproto.Reject_WrongUserPW, "")
return
} else {
if server.CheckSuperUserPassword(*auth.Password) {
ok := false
client.user, ok = server.UserNameMap[client.Username]
if !ok {
client.RejectAuth(mumbleproto.Reject_InvalidUsername, "")
@ -1155,7 +1166,7 @@ func (server *Server) RemoveExpiredBans() {
}
// Is the incoming connection conn banned?
func (server *Server) IsBanned(conn net.Conn) bool {
func (server *Server) IsConnectionBanned(conn net.Conn) bool {
server.banlock.RLock()
defer server.banlock.RUnlock()
@ -1169,6 +1180,20 @@ func (server *Server) IsBanned(conn net.Conn) bool {
return false
}
// Is the certificate hash banned?
func (server *Server) IsCertHashBanned(hash string) bool {
server.banlock.RLock()
defer server.banlock.RUnlock()
for _, ban := range server.Bans {
if ban.CertHash == hash && !ban.IsExpired() {
return true
}
}
return false
}
// Filter incoming text according to the server's current rules.
func (server *Server) FilterText(text string) (filtered string, err error) {
options := &htmlfilter.Options{
@ -1197,8 +1222,8 @@ func (server *Server) acceptLoop() {
// Remove expired bans
server.RemoveExpiredBans()
// Is the client banned?
if server.IsBanned(conn) {
// Is the client IP-banned?
if server.IsConnectionBanned(conn) {
server.Printf("Rejected client %v: Banned", conn.RemoteAddr())
err := conn.Close()
if err != nil {
@ -1209,7 +1234,7 @@ func (server *Server) acceptLoop() {
// Create a new client connection from our *tls.Conn
// which wraps net.TCPConn.
err = server.NewClient(conn)
err = server.handleIncomingClient(conn)
if err != nil {
server.Printf("Unable to handle new client: %v", err)
continue