import (
"archive/tar"
"bytes"
+ "crypto/tls"
"encoding/json"
"errors"
"flag"
"io"
"io/fs"
"log"
+ "net/http"
"net/url"
"os"
"os/exec"
"time"
"github.com/davecgh/go-spew/spew"
+ "github.com/gorilla/websocket"
"github.com/mattermost/mattermost-server/v6/model"
"go.cypherpunks.ru/netrc"
"go.stargrave.org/mmc"
func main() {
entrypoint := flag.String("entrypoint", mmc.GetEntrypoint(), "Entrypoint")
+ spkiHash := flag.String("spki", mmc.GetSPKIHash(), "Entrypoint's SPKI hash")
notifyCmd := flag.String("notify", "cmd/notify", "Path to notification handler")
heartbeatCh := flag.String("heartbeat-ch", "town-square", "Channel for heartbeating")
flag.Parse()
log.Fatalln("no credentials found for:", entrypointURL.Hostname())
}
c := model.NewAPIv4Client(*entrypoint)
+ c.HTTPClient.Transport = &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
+ ForceAttemptHTTP2: true,
+ MaxIdleConns: 100,
+ IdleConnTimeout: 90 * time.Second,
+ TLSHandshakeTimeout: 10 * time.Second,
+ ExpectContinueTimeout: 1 * time.Second,
+ TLSClientConfig: &tls.Config{
+ ServerName: entrypointURL.Hostname(),
+ InsecureSkipVerify: true,
+ VerifyPeerCertificate: mmc.NewVerifyPeerCertificate(*spkiHash),
+ },
+ }
+
c.Login(login, password)
me, resp, err := c.GetMe("")
if err != nil {
default:
log.Println("unhandled scheme:", entrypointURL.Scheme)
}
- wc, err := model.NewWebSocketClient4(entrypointURL.String(), c.AuthToken)
+ wc, err := model.NewWebSocketClient4WithDialer(
+ &websocket.Dialer{
+ TLSClientConfig: &tls.Config{
+ ServerName: entrypointURL.Hostname(),
+ InsecureSkipVerify: true,
+ VerifyPeerCertificate: mmc.NewVerifyPeerCertificate(*spkiHash),
+ },
+ }, entrypointURL.String(), c.AuthToken,
+ )
if err != nil {
log.Fatalln(err)
}
package mmc
import (
+ "crypto/sha256"
+ "crypto/x509"
+ "encoding/hex"
+ "errors"
"os"
"strings"
"time"
}
return s
}
+
+func GetSPKIHash() string {
+ s := os.Getenv("MMC_SPKI")
+ if s == "" {
+ return "deadbeef"
+ }
+ return s
+}
+
+func NewVerifyPeerCertificate(hashExpected string) func(
+ rawCerts [][]byte, verifiedChains [][]*x509.Certificate,
+) error {
+ return func(
+ rawCerts [][]byte, verifiedChains [][]*x509.Certificate,
+ ) error {
+ cer, err := x509.ParseCertificate(rawCerts[0])
+ if err != nil {
+ return err
+ }
+ spki := cer.RawSubjectPublicKeyInfo
+ hsh := sha256.Sum256(spki)
+ if hashExpected != hex.EncodeToString(hsh[:]) {
+ return errors.New("server certificate's SPKI hash mismatch")
+ }
+ return nil
+ }
+}