mirror of
https://github.com/shazow/ssh-chat.git
synced 2025-04-14 16:17:17 +03:00
Merge pull request #72 from empathetic-alligator/master
Can now whitelist users by github pubkeys.
This commit is contained in:
commit
1d64f59c0c
25
client.go
25
client.go
@ -32,13 +32,14 @@ const (
|
||||
|
||||
// OpHelpText is the additional text returned by /help if the client is an Op
|
||||
OpHelpText string = systemMessageFormat + `-> Available operator commands:
|
||||
/ban $NAME - Banish a user from the chat
|
||||
/kick $NAME - Kick em' out.
|
||||
/op $NAME - Promote a user to server operator.
|
||||
/silence $NAME - Revoke a user's ability to speak.
|
||||
/shutdown $MESSAGE - Broadcast message and shutdown server.
|
||||
/motd $MESSAGE - Set message shown whenever somebody joins.
|
||||
/whitelist $FINGERPRINT - Add fingerprint to whitelist, prevent anyone else from joining.` + Reset
|
||||
/ban $NAME - Banish a user from the chat
|
||||
/kick $NAME - Kick em' out.
|
||||
/op $NAME - Promote a user to server operator.
|
||||
/silence $NAME - Revoke a user's ability to speak.
|
||||
/shutdown $MESSAGE - Broadcast message and shutdown server.
|
||||
/motd $MESSAGE - Set message shown whenever somebody joins.
|
||||
/whitelist $FINGERPRINT - Add fingerprint to whitelist, prevent anyone else from joining.
|
||||
/whitelist github.com/$USER - Add github user's pubkeys to whitelist.` + Reset
|
||||
|
||||
// AboutText is the text returned by /about
|
||||
AboutText string = systemMessageFormat + `-> ssh-chat is made by @shazow.
|
||||
@ -415,8 +416,14 @@ func (c *Client) handleShell(channel ssh.Channel) {
|
||||
c.SysMsg("Missing $FINGERPRINT from: /whitelist $FINGERPRINT")
|
||||
} else {
|
||||
fingerprint := parts[1]
|
||||
c.Server.Whitelist(fingerprint)
|
||||
c.SysMsg("Added %s to the whitelist", fingerprint)
|
||||
go func() {
|
||||
err = c.Server.Whitelist(fingerprint)
|
||||
if err != nil {
|
||||
c.SysMsg("Error adding to whitelist: %s", err)
|
||||
} else {
|
||||
c.SysMsg("Added %s to the whitelist", fingerprint)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
default:
|
||||
|
75
server.go
75
server.go
@ -9,6 +9,9 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
"net/http"
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
@ -263,11 +266,81 @@ func (s *Server) Op(fingerprint string) {
|
||||
}
|
||||
|
||||
// Whitelist adds the given fingerprint to the whitelist
|
||||
func (s *Server) Whitelist(fingerprint string) {
|
||||
func (s *Server) Whitelist(fingerprint string) error {
|
||||
if strings.HasPrefix(fingerprint, "github.com/") {
|
||||
return s.whitelistIdentityURL(fingerprint)
|
||||
}
|
||||
|
||||
return s.whitelistFingerprint(fingerprint)
|
||||
}
|
||||
|
||||
func (s *Server) whitelistIdentityURL(user string) error {
|
||||
logger.Infof("Adding github account %s to whitelist", user)
|
||||
|
||||
user = strings.Replace(user, "github.com/", "", -1)
|
||||
keys, err := getGithubPubKeys(user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(keys) == 0 {
|
||||
return fmt.Errorf("No keys for github user %s", user)
|
||||
}
|
||||
for _, key := range keys {
|
||||
fingerprint := Fingerprint(key)
|
||||
s.whitelistFingerprint(fingerprint)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) whitelistFingerprint(fingerprint string) error {
|
||||
logger.Infof("Adding whitelist: %s", fingerprint)
|
||||
s.Lock()
|
||||
s.whitelist[fingerprint] = struct{}{}
|
||||
s.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Client for getting github pub keys
|
||||
var timeout = time.Duration(10 * time.Second)
|
||||
var client = http.Client{
|
||||
Timeout: timeout,
|
||||
}
|
||||
// Returns an array of public keys for the given github user URL
|
||||
func getGithubPubKeys(user string) ([]ssh.PublicKey, error) {
|
||||
resp, err := client.Get("http://github.com/" + user + ".keys")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
pubs := []ssh.PublicKey{}
|
||||
scanner := bufio.NewScanner(resp.Body)
|
||||
for scanner.Scan() {
|
||||
text := scanner.Text()
|
||||
if text == "Not Found" {
|
||||
continue
|
||||
}
|
||||
|
||||
splitKey := strings.SplitN(text, " ", -1)
|
||||
|
||||
// In case of malformated key
|
||||
if len(splitKey) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
bodyDecoded, err := base64.StdEncoding.DecodeString(splitKey[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pub, err := ssh.ParsePublicKey(bodyDecoded)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pubs = append(pubs, pub)
|
||||
}
|
||||
return pubs, nil
|
||||
}
|
||||
|
||||
// Uptime returns the time since the server was started
|
||||
|
Loading…
x
Reference in New Issue
Block a user