chore: basic working matrix interface

This commit is contained in:
0x1a8510f2 2023-06-04 14:48:45 +01:00
parent 58d53eab76
commit d129fc97a4
Signed by: 0x1a8510f2
GPG Key ID: 1C692E355D76775D
5 changed files with 133 additions and 73 deletions

View File

@ -4,7 +4,6 @@ import (
"net/url"
"os"
"strconv"
"strings"
"time"
"dev.l1qu1d.net/wraith-labs/wraith-module-pinecomms/internal/proto"
@ -28,8 +27,8 @@ type Config struct {
// The password to authenticate to the HS with.
password string
// List of MXIDs with admin privileges over the C2.
admins []string
// The Matrix room where administration occurs.
adminRoom string
// Private key to use as identity on the pinecone network.
pineconeId string
@ -68,7 +67,7 @@ func (c *Config) Setup() {
c.homeserver = os.Getenv("WMP_HOMESERVER")
c.username = os.Getenv("WMP_USERNAME")
c.password = os.Getenv("WMP_PASSWORD")
c.admins = strings.Split(os.Getenv("WMP_ADMINS"), " ")
c.adminRoom = os.Getenv("WMP_ADMIN_ROOM")
c.pineconeId = os.Getenv("WMP_ID_PINECONE")
c.logPinecone = logPinecone
c.pineconeInboundTcpAddr = os.Getenv("WMP_INBOUND_TCP_PINECONE")
@ -87,6 +86,10 @@ func (c *Config) Setup() {
}
if c.username == "" || c.password == "" {
panic("please provide homeserver username and password")
panic("please provide homeserver credentials")
}
if c.adminRoom == "" {
panic("please provide an admin room id")
}
}

View File

@ -4,7 +4,6 @@ import (
"context"
"crypto/ed25519"
"encoding/hex"
"errors"
"fmt"
"log"
"os"
@ -16,14 +15,12 @@ import (
"dev.l1qu1d.net/wraith-labs/wraith-module-pinecomms/internal/proto"
"dev.l1qu1d.net/wraith-labs/wraith-module-pinecomms/internal/radio"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/crypto/cryptohelper"
"maunium.net/go/mautrix/event"
_ "github.com/mattn/go-sqlite3"
)
func main() {
//
// Create a struct to hold any config values.
// Create a struct to hold config values.
//
c := Config{}
@ -48,13 +45,13 @@ func main() {
}
pineconeId := ed25519.PrivateKey(pineconeIdBytes)
// Get a struct for managing pinecone connections.
pr := radio.GetInstance()
//
// Configure pinecone manager.
//
// Get a struct for managing pinecone connections.
pr := radio.GetInstance()
pr.SetPineconeIdentity(pineconeId)
if c.logPinecone {
pr.SetLogger(log.Default())
@ -74,6 +71,15 @@ func main() {
sigchan := make(chan os.Signal, 2)
signal.Notify(sigchan, syscall.SIGTERM, syscall.SIGINT)
//
// Set up Matrix comms for C2.
//
matrixBotCtx, stopMatrixBot := context.WithCancel(context.Background())
var matrixBotWait sync.WaitGroup
client := MatrixBotInit(matrixBotCtx, c, &matrixBotWait)
MatrixBotRunStartup(client, c)
MatrixBotEventHandlerSetUp(client, c)
//
// Main body.
//
@ -84,68 +90,9 @@ func main() {
// Start pinecone.
go pr.Start()
// Connect to Matrix homeserver.
client, err := mautrix.NewClient(c.homeserver, "", "")
if err != nil {
panic(err)
}
syncer := client.Syncer.(*mautrix.DefaultSyncer)
syncer.OnEventType(event.EventMessage, func(source mautrix.EventSource, evt *event.Event) {
//
})
syncer.OnEventType(event.StateMember, func(source mautrix.EventSource, evt *event.Event) {
if evt.GetStateKey() == client.UserID.String() && evt.Content.AsMember().Membership == event.MembershipInvite {
_, err := client.JoinRoomByID(evt.RoomID)
if err == nil {
//
} else {
}
}
})
cryptoHelper, err := cryptohelper.NewCryptoHelper(client, []byte("meow"), "file::memory:")
if err != nil {
panic(err)
}
// You can also store the user/device IDs and access token and put them in the client beforehand instead of using LoginAs.
//client.UserID = "..."
//client.DeviceID = "..."
//client.AccessToken = "..."
// You don't need to set a device ID in LoginAs because the crypto helper will set it for you if necessary.
cryptoHelper.LoginAs = &mautrix.ReqLogin{
Type: mautrix.AuthTypePassword,
Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: c.username},
Password: c.password,
}
// If you want to use multiple clients with the same DB, you should set a distinct database account ID for each one.
//cryptoHelper.DBAccountID = ""
err = cryptoHelper.Init()
if err != nil {
panic(err)
}
// Set the client crypto helper in order to automatically encrypt outgoing messages
client.Crypto = cryptoHelper
syncCtx, cancelSync := context.WithCancel(context.Background())
var syncStopWait sync.WaitGroup
syncStopWait.Add(1)
go func() {
err = client.SyncWithContext(syncCtx)
defer syncStopWait.Done()
if err != nil && !errors.Is(err, context.Canceled) {
panic(err)
}
}()
cancelSync()
syncStopWait.Wait()
_ = cryptoHelper.Close()
client.JoinedRooms()
// Start receiving messages.
// Start receiving Wraith messages.
// Background context is okay because the channel will be closed
// when the manager exits further down anyway.
recv := pr.RecvChan(context.Background())
@ -204,7 +151,12 @@ mainloop:
os.Exit(1)
}()
// Stop pinecone.
pr.Stop()
// Stop Matrix bot.
stopMatrixBot()
matrixBotWait.Wait()
os.Exit(0)
}

103
cmd/pc3/matrix.go Normal file
View File

@ -0,0 +1,103 @@
package main
import (
"context"
"crypto/rand"
"errors"
"fmt"
"sync"
"time"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/crypto/cryptohelper"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
)
func MatrixBotRunStartup(client *mautrix.Client, c Config) {
// Make sure we're only ever in the admin room.
rooms, err := client.JoinedRooms()
if err != nil {
panic(err)
}
for _, room := range rooms.JoinedRooms {
if room.String() != c.adminRoom {
client.LeaveRoom(room)
}
}
}
func MatrixBotEventHandlerSetUp(client *mautrix.Client, c Config) {
syncer := client.Syncer.(*mautrix.DefaultSyncer)
syncer.OnEventType(event.EventMessage, func(source mautrix.EventSource, evt *event.Event) {
if evt.RoomID == id.RoomID(c.adminRoom) {
client.SendMessageEvent(evt.RoomID, event.EventReaction, &map[string]any{
"m.relates_to": map[string]any{
"event_id": evt.ID,
"key": "🌊",
"rel_type": "m.annotation",
},
})
}
})
syncer.OnEventType(event.StateMember, func(source mautrix.EventSource, evt *event.Event) {
if evt.GetStateKey() == client.UserID.String() && evt.Content.AsMember().Membership == event.MembershipInvite {
if evt.RoomID == id.RoomID(c.adminRoom) {
client.JoinRoomByID(evt.RoomID)
} else {
client.LeaveRoom(evt.RoomID)
}
}
})
}
func MatrixBotInit(ctx context.Context, c Config, wg *sync.WaitGroup) *mautrix.Client {
// Connect to Matrix homeserver.
client, err := mautrix.NewClient(c.homeserver, "", "")
if err != nil {
panic(err)
}
pickleKey := make([]byte, 64)
_, err = rand.Read(pickleKey)
if err != nil {
panic(err)
}
cryptoHelper, err := cryptohelper.NewCryptoHelper(client, pickleKey, "file::memory:")
if err != nil {
panic(err)
}
cryptoHelper.LoginAs = &mautrix.ReqLogin{
Type: mautrix.AuthTypePassword,
Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: c.username},
InitialDeviceDisplayName: "WMP-" + fmt.Sprint(time.Now().Unix()),
Password: c.password,
StoreHomeserverURL: true,
}
// Set the client crypto helper in order to automatically encrypt outgoing messages.
err = cryptoHelper.Init()
if err != nil {
panic(err)
}
client.Crypto = cryptoHelper
wg.Add(1)
go func() {
defer wg.Done()
defer cryptoHelper.Close()
for {
err := client.SyncWithContext(ctx)
if err == nil || errors.Is(err, context.Canceled) {
break
}
}
}()
return client
}

1
go.mod
View File

@ -9,6 +9,7 @@ require (
github.com/gorilla/mux v1.8.0
github.com/gorilla/websocket v1.5.0
github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a
github.com/mattn/go-sqlite3 v1.14.16
maunium.net/go/mautrix v0.15.2
)

1
go.sum
View File

@ -65,6 +65,7 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=