diff --git a/bridgestate.go b/bridgestate.go index 3243221..e9798a6 100644 --- a/bridgestate.go +++ b/bridgestate.go @@ -27,6 +27,7 @@ const ( GMListenError status.BridgeStateErrorCode = "gm-listen-error" GMFatalError status.BridgeStateErrorCode = "gm-listen-fatal-error" GMUnpaired status.BridgeStateErrorCode = "gm-unpaired" + GMUnpairedGaia status.BridgeStateErrorCode = "gm-unpaired-gaia" GMUnpaired404 status.BridgeStateErrorCode = "gm-unpaired-entity-not-found" GMNotConnected status.BridgeStateErrorCode = "gm-not-connected" GMConnecting status.BridgeStateErrorCode = "gm-connecting" @@ -49,12 +50,13 @@ func init() { GMFatalError: "Fatal error polling messages from Google Messages server, please re-link the bridge", GMUnpaired: "Unpaired from Google Messages, please re-link the connection to continue using SMS/RCS", GMUnpaired404: "Unpaired from Google Messages, please re-link the connection to continue using SMS/RCS", + GMUnpairedGaia: "Unpaired from Google Messages, please re-link the connection to continue using SMS/RCS", GMNotDefaultSMSApp: "Google Messages isn't set as the default SMS app. Please set the default SMS app on your Android phone to Google Messages to continue using SMS/RCS.", GMBrowserInactive: "Google Messages opened in another browser", GMBrowserInactiveTimeout: "Google Messages disconnected due to timeout", GMBrowserInactiveInactivity: "Google Messages disconnected due to inactivity", GMPhoneNotResponding: "Your phone is not responding, please check that it is connected to the internet. You may need to open the Messages app on your phone for it to reconnect.", - GMSwitchedToGoogleLogin: "Please switch to the QR code pairing method in the Google Messages app to continue using SMS/RCS", + GMSwitchedToGoogleLogin: "You switched to Google account pairing, please log in to continue using SMS/RCS", }) } diff --git a/commands.go b/commands.go index 19c4785..d8d98cd 100644 --- a/commands.go +++ b/commands.go @@ -17,6 +17,7 @@ package main import ( + "encoding/json" "fmt" "strings" @@ -40,7 +41,8 @@ type WrappedCommandEvent struct { func (br *GMBridge) RegisterCommands() { proc := br.CommandProcessor.(*commands.Processor) proc.AddHandlers( - cmdLogin, + cmdLoginQR, + cmdLoginGoogle, cmdDeleteSession, cmdLogout, cmdReconnect, @@ -70,16 +72,17 @@ var ( HelpSectionPortalManagement = commands.HelpSection{Name: "Portal management", Order: 20} ) -var cmdLogin = &commands.FullHandler{ - Func: wrapCommand(fnLogin), - Name: "login", +var cmdLoginQR = &commands.FullHandler{ + Func: wrapCommand(fnLoginQR), + Name: "login-qr", + Aliases: []string{"login"}, Help: commands.HelpMeta{ Section: commands.HelpSectionAuth, - Description: "Link the bridge to Google Messages on your Android phone as a web client.", + Description: "Link the bridge to Google Messages on your Android phone by scanning a QR code.", }, } -func fnLogin(ce *WrappedCommandEvent) { +func fnLoginQR(ce *WrappedCommandEvent) { if ce.User.Session != nil { if ce.User.IsConnected() { ce.Reply("You're already logged in") @@ -123,6 +126,64 @@ func fnLogin(ce *WrappedCommandEvent) { ce.ZLog.Trace().Msg("Login command finished") } +var cmdLoginGoogle = &commands.FullHandler{ + Func: wrapCommand(fnLoginGoogle), + Name: "login-google", + Aliases: []string{"login"}, + Help: commands.HelpMeta{ + Section: commands.HelpSectionAuth, + Description: "Link the bridge to Google Messages on your Android phone by logging in with your Google account.", + }, +} + +func fnLoginGoogle(ce *WrappedCommandEvent) { + if ce.User.Session != nil { + if ce.User.IsConnected() { + ce.Reply("You're already logged in") + } else { + ce.Reply("You're already logged in. Perhaps you wanted to `reconnect`?") + } + return + } else if ce.User.pairSuccessChan != nil { + ce.Reply("You already have a login in progress") + return + } + ce.User.CommandState = &commands.CommandState{ + Next: commands.MinimalHandlerFunc(wrapCommand(fnLoginGoogleCookies)), + Action: "Login", + } + ce.Reply("Send your Google cookies here, formatted as a key-value JSON object (see for details)") +} + +func fnLoginGoogleCookies(ce *WrappedCommandEvent) { + ce.User.CommandState = nil + if ce.User.Session != nil { + if ce.User.IsConnected() { + ce.Reply("You're already logged in") + } else { + ce.Reply("You're already logged in. Perhaps you wanted to `reconnect`?") + } + return + } else if ce.User.pairSuccessChan != nil { + ce.Reply("You already have a login in progress") + return + } + var cookies map[string]string + err := json.Unmarshal([]byte(ce.RawArgs), &cookies) + if err != nil { + ce.Reply("Failed to parse cookies: %v", err) + return + } + err = ce.User.LoginGoogle(cookies, func(emoji string) { + ce.Reply(emoji) + }) + if err != nil { + ce.Reply("Login failed: %v", err) + } else { + ce.Reply("Login successful") + } +} + func (user *User) sendQREdit(ce *WrappedCommandEvent, content *event.MessageEventContent, prevEvent id.EventID) id.EventID { if len(prevEvent) != 0 { content.SetEdit(prevEvent) diff --git a/go.mod b/go.mod index 1200e2e..78d8379 100644 --- a/go.mod +++ b/go.mod @@ -1,17 +1,17 @@ module go.mau.fi/mautrix-gmessages -go 1.20 +go 1.21 require ( github.com/gabriel-vasile/mimetype v1.4.3 github.com/lib/pq v1.10.9 - github.com/mattn/go-sqlite3 v1.14.19 - github.com/rs/zerolog v1.31.0 + github.com/mattn/go-sqlite3 v1.14.22 + github.com/rs/zerolog v1.32.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e go.mau.fi/mautrix-gmessages/libgm v0.2.2 go.mau.fi/util v0.2.1 - golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 - google.golang.org/protobuf v1.31.0 + golang.org/x/exp v0.0.0-20240213143201-ec583247a57a + google.golang.org/protobuf v1.32.0 maunium.net/go/maulogger/v2 v2.4.1 maunium.net/go/mautrix v0.16.2 ) @@ -19,7 +19,7 @@ require ( require ( github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/kr/pretty v0.3.1 // indirect @@ -32,9 +32,9 @@ require ( github.com/tidwall/sjson v1.2.5 // indirect github.com/yuin/goldmark v1.6.0 // indirect go.mau.fi/zeroconfig v0.1.2 // indirect - golang.org/x/crypto v0.15.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/net v0.18.0 // indirect - golang.org/x/sys v0.14.0 // indirect + golang.org/x/sys v0.17.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 7f424fc..43f80b5 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,17 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= @@ -30,20 +30,22 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= -github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -59,21 +61,19 @@ go.mau.fi/util v0.2.1 h1:eazulhFE/UmjOFtPrGg6zkF5YfAyiDzQb8ihLMbsPWw= go.mau.fi/util v0.2.1/go.mod h1:MjlzCQEMzJ+G8RsPawHzpLB8rwTo3aPIjG5FzBvQT/c= go.mau.fi/zeroconfig v0.1.2 h1:DKOydWnhPMn65GbXZOafgkPm11BvFashZWLct0dGFto= go.mau.fi/zeroconfig v0.1.2/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70= -golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= -golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= -golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611 h1:qCEDpW1G+vcj3Y7Fy52pEM1AWm3abj8WimGYejI3SC4= -golang.org/x/exp v0.0.0-20231214170342-aacd6d4b4611/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/libgm/client.go b/libgm/client.go index 4d42dc4..9a17c1a 100644 --- a/libgm/client.go +++ b/libgm/client.go @@ -8,7 +8,6 @@ import ( "io" "net/http" "net/url" - "strconv" "time" "github.com/google/uuid" @@ -34,6 +33,18 @@ type AuthData struct { TachyonTTL int64 `json:"tachyon_ttl,omitempty"` // Unknown encryption key, not used for anything WebEncryptionKey []byte `json:"web_encryption_key,omitempty"` + + SessionID uuid.UUID `json:"session_id,omitempty"` + DestRegID uuid.UUID `json:"dest_reg_id,omitempty"` + PairingID uuid.UUID `json:"pairing_id,omitempty"` + Cookies map[string]string `json:"cookies,omitempty"` +} + +func (ad *AuthData) AuthNetwork() string { + if ad.Cookies != nil { + return util.GoogleNetwork + } + return "" } const RefreshTachyonBuffer = 1 * time.Hour @@ -64,6 +75,7 @@ type Client struct { conversationsFetchedOnce bool AuthData *AuthData + cfg *gmproto.Config proxy Proxy http *http.Client @@ -89,9 +101,15 @@ func NewClient(authData *AuthData, logger zerolog.Logger) *Client { pingShortCircuit: make(chan struct{}), } sessionHandler.client = cli - err := cli.FetchConfigVersion() + var err error + cli.cfg, err = cli.FetchConfig() if err != nil { - cli.Logger.Warn().Err(err).Msg("Failed to fetch latest web version") + cli.Logger.Err(err).Msg("Failed to fetch web config") + } else if deviceID := cli.cfg.GetDeviceInfo().GetDeviceID(); deviceID != "" { + authData.SessionID, err = uuid.Parse(deviceID) + if err != nil { + cli.Logger.Err(err).Str("device_id", deviceID).Msg("Failed to parse device ID") + } } return cli } @@ -130,11 +148,11 @@ func (c *Client) Connect() error { return fmt.Errorf("failed to refresh auth token: %w", err) } - webEncryptionKeyResponse, err := c.GetWebEncryptionKey() - if err != nil { - return fmt.Errorf("failed to get web encryption key: %w", err) - } - c.updateWebEncryptionKey(webEncryptionKeyResponse.GetKey()) + //webEncryptionKeyResponse, err := c.GetWebEncryptionKey() + //if err != nil { + // return fmt.Errorf("failed to get web encryption key: %w", err) + //} + //c.updateWebEncryptionKey(webEncryptionKeyResponse.GetKey()) go c.doLongPoll(true) c.sessionHandler.startAckInterval() go c.postConnect() @@ -150,6 +168,10 @@ func (c *Client) postConnect() { }) return } + if c.AuthData.Mobile.Network != util.QRNetwork { + // Don't check bugle default unless using bugle + return + } doneChan := make(chan struct{}) go func() { @@ -166,7 +188,6 @@ func (c *Client) postConnect() { return } c.Logger.Debug().Bool("bugle_default", bugleRes.Success).Msg("Got is bugle default response on connect") - } func (c *Client) Disconnect() { @@ -200,25 +221,29 @@ func (c *Client) triggerEvent(evt interface{}) { } } -func (c *Client) FetchConfigVersion() error { +func (c *Client) FetchConfig() (*gmproto.Config, error) { req, err := http.NewRequest(http.MethodGet, util.ConfigURL, nil) if err != nil { - return fmt.Errorf("failed to prepare request: %w", err) + return nil, fmt.Errorf("failed to prepare request: %w", err) } + util.BuildRelayHeaders(req, "", "*/*") + req.Header.Set("sec-fetch-site", "same-origin") + req.Header.Del("x-user-agent") + req.Header.Del("origin") + c.AddCookieHeaders(req) - configRes, err := c.http.Do(req) + resp, err := c.http.Do(req) + if resp != nil { + c.HandleCookieUpdates(resp) + } + config, err := typedHTTPResponse[*gmproto.Config](resp, err) if err != nil { - return fmt.Errorf("failed to send request: %w", err) + return nil, err } - responseBody, err := io.ReadAll(configRes.Body) - if err != nil { - return fmt.Errorf("failed to read response body: %w", err) - } - - version, parseErr := util.ParseConfigVersion(responseBody) + version, parseErr := config.ParsedClientVersion() if parseErr != nil { - return fmt.Errorf("failed to parse response body: %w", err) + return nil, fmt.Errorf("failed to parse client version: %w", err) } currVersion := util.ConfigMessage @@ -228,7 +253,8 @@ func (c *Client) FetchConfigVersion() error { } else { c.Logger.Debug().Any("version", currVersion).Msg("Using latest messages for web version") } - return nil + + return config, nil } func (c *Client) diffVersionFormat(curr *gmproto.ConfigVersion, latest *gmproto.ConfigVersion) string { @@ -240,17 +266,17 @@ func (c *Client) updateWebEncryptionKey(key []byte) { c.AuthData.WebEncryptionKey = key } -func (c *Client) updateTachyonAuthToken(t []byte, validFor int64) { - c.AuthData.TachyonAuthToken = t - validForDuration := time.Duration(validFor) * time.Microsecond +func (c *Client) updateTachyonAuthToken(data *gmproto.TokenData) { + c.AuthData.TachyonAuthToken = data.GetTachyonAuthToken() + validForDuration := time.Duration(data.GetTTL()) * time.Microsecond if validForDuration == 0 { validForDuration = 24 * time.Hour } - c.AuthData.TachyonExpiry = time.Now().UTC().Add(time.Microsecond * time.Duration(validFor)) + c.AuthData.TachyonExpiry = time.Now().UTC().Add(validForDuration) c.AuthData.TachyonTTL = validForDuration.Microseconds() c.Logger.Debug(). Time("tachyon_expiry", c.AuthData.TachyonExpiry). - Int64("valid_for", validFor). + Int64("valid_for", data.GetTTL()). Msg("Updated tachyon token") } @@ -275,6 +301,7 @@ func (c *Client) refreshAuthToken() error { MessageAuth: &gmproto.AuthMessage{ RequestID: requestID, TachyonAuthToken: c.AuthData.TachyonAuthToken, + Network: c.AuthData.AuthNetwork(), ConfigVersion: util.ConfigMessage, }, CurrBrowserDevice: c.AuthData.Browser, @@ -291,14 +318,11 @@ func (c *Client) refreshAuthToken() error { return err } - token := resp.GetTokenData().GetTachyonAuthToken() - if token == nil { + if resp.GetTokenData().GetTachyonAuthToken() == nil { return fmt.Errorf("no tachyon auth token in refresh response") } - validFor, _ := strconv.ParseInt(resp.GetTokenData().GetValidFor(), 10, 64) - - c.updateTachyonAuthToken(token, validFor) + c.updateTachyonAuthToken(resp.GetTokenData()) c.triggerEvent(&events.AuthTokenRefreshed{}) return nil } diff --git a/libgm/event_handler.go b/libgm/event_handler.go index 392198e..714ae38 100644 --- a/libgm/event_handler.go +++ b/libgm/event_handler.go @@ -1,6 +1,7 @@ package libgm import ( + "bytes" "crypto/sha256" "encoding/base64" "fmt" @@ -18,6 +19,7 @@ type IncomingRPCMessage struct { IsOld bool Pair *gmproto.RPCPairData + Gaia *gmproto.RPCGaiaData Message *gmproto.RPCMessageData DecryptedData []byte @@ -57,6 +59,15 @@ func (c *Client) decryptInternalMessage(data *gmproto.IncomingRPCMessage) (*Inco Msg("Errored pair event content") return nil, fmt.Errorf("failed to decode pair event: %w", err) } + case gmproto.BugleRoute_GaiaEvent: + msg.Gaia = &gmproto.RPCGaiaData{} + err := proto.Unmarshal(data.GetMessageData(), msg.Gaia) + if err != nil { + c.Logger.Trace(). + Str("data", base64.StdEncoding.EncodeToString(msg.GetMessageData())). + Msg("Errored gaia event content") + return nil, fmt.Errorf("failed to decode gaia event: %w", err) + } case gmproto.BugleRoute_DataEvent: msg.Message = &gmproto.RPCMessageData{} err := proto.Unmarshal(data.GetMessageData(), msg.Message) @@ -176,6 +187,8 @@ func (c *Client) HandleRPCMsg(rawMsg *gmproto.IncomingRPCMessage) { switch msg.BugleRoute { case gmproto.BugleRoute_PairEvent: c.handlePairingEvent(msg) + case gmproto.BugleRoute_GaiaEvent: + c.handleGaiaPairingEvent(msg) case gmproto.BugleRoute_DataEvent: if c.skipCount > 0 { c.skipCount-- @@ -191,9 +204,15 @@ type WrappedMessage struct { Data []byte } +var hackyLoggedOutBytes = []byte{0x72, 0x00} + func (c *Client) handleUpdatesEvent(msg *IncomingRPCMessage) { switch msg.Message.Action { case gmproto.ActionType_GET_UPDATES: + if msg.DecryptedData == nil && bytes.Equal(msg.Message.UnencryptedData, hackyLoggedOutBytes) { + c.triggerEvent(&events.GaiaLoggedOut{}) + return + } data, ok := msg.DecryptedMessage.(*gmproto.UpdateEvents) if !ok { c.Logger.Error(). @@ -256,11 +275,13 @@ func (c *Client) handleUpdatesEvent(msg *IncomingRPCMessage) { default: c.Logger.Warn(). - Str("evt_data", base64.StdEncoding.EncodeToString(msg.DecryptedData)). + Str("evt_data", base64.StdEncoding.EncodeToString(msg.GetMessageData())). + Str("decrypted_data", base64.StdEncoding.EncodeToString(msg.DecryptedData)). Msg("Got unknown event type") } default: c.Logger.Debug(). + Str("evt_data", base64.StdEncoding.EncodeToString(msg.GetMessageData())). Str("request_id", msg.Message.SessionID). Str("action_type", msg.Message.Action.String()). Bool("is_old", msg.IsOld). diff --git a/libgm/events/ready.go b/libgm/events/ready.go index 67a1c7c..0f7cb77 100644 --- a/libgm/events/ready.go +++ b/libgm/events/ready.go @@ -15,6 +15,8 @@ type ClientReady struct { type AuthTokenRefreshed struct{} +type GaiaLoggedOut struct{} + type AccountChange struct { *gmproto.AccountChangeOrSomethingEvent IsFake bool diff --git a/libgm/gmproto/authentication.pb.go b/libgm/gmproto/authentication.pb.go index 07aa733..50a688a 100644 --- a/libgm/gmproto/authentication.pb.go +++ b/libgm/gmproto/authentication.pb.go @@ -351,6 +351,400 @@ func (x *ConfigVersion) GetV2() int32 { return 0 } +type SignInGaiaRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AuthMessage *AuthMessage `protobuf:"bytes,1,opt,name=authMessage,proto3" json:"authMessage,omitempty"` + Inner *SignInGaiaRequest_Inner `protobuf:"bytes,2,opt,name=inner,proto3" json:"inner,omitempty"` + UnknownInt3 int32 `protobuf:"varint,3,opt,name=unknownInt3,proto3" json:"unknownInt3,omitempty"` + Network string `protobuf:"bytes,4,opt,name=network,proto3" json:"network,omitempty"` +} + +func (x *SignInGaiaRequest) Reset() { + *x = SignInGaiaRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignInGaiaRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignInGaiaRequest) ProtoMessage() {} + +func (x *SignInGaiaRequest) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignInGaiaRequest.ProtoReflect.Descriptor instead. +func (*SignInGaiaRequest) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{3} +} + +func (x *SignInGaiaRequest) GetAuthMessage() *AuthMessage { + if x != nil { + return x.AuthMessage + } + return nil +} + +func (x *SignInGaiaRequest) GetInner() *SignInGaiaRequest_Inner { + if x != nil { + return x.Inner + } + return nil +} + +func (x *SignInGaiaRequest) GetUnknownInt3() int32 { + if x != nil { + return x.UnknownInt3 + } + return 0 +} + +func (x *SignInGaiaRequest) GetNetwork() string { + if x != nil { + return x.Network + } + return "" +} + +type SignInGaiaResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Header *SignInGaiaResponse_Header `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` + MaybeBrowserUUID string `protobuf:"bytes,2,opt,name=maybeBrowserUUID,proto3" json:"maybeBrowserUUID,omitempty"` + DeviceData *SignInGaiaResponse_DeviceData `protobuf:"bytes,3,opt,name=deviceData,proto3" json:"deviceData,omitempty"` + TokenData *TokenData `protobuf:"bytes,4,opt,name=tokenData,proto3" json:"tokenData,omitempty"` +} + +func (x *SignInGaiaResponse) Reset() { + *x = SignInGaiaResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignInGaiaResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignInGaiaResponse) ProtoMessage() {} + +func (x *SignInGaiaResponse) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignInGaiaResponse.ProtoReflect.Descriptor instead. +func (*SignInGaiaResponse) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{4} +} + +func (x *SignInGaiaResponse) GetHeader() *SignInGaiaResponse_Header { + if x != nil { + return x.Header + } + return nil +} + +func (x *SignInGaiaResponse) GetMaybeBrowserUUID() string { + if x != nil { + return x.MaybeBrowserUUID + } + return "" +} + +func (x *SignInGaiaResponse) GetDeviceData() *SignInGaiaResponse_DeviceData { + if x != nil { + return x.DeviceData + } + return nil +} + +func (x *SignInGaiaResponse) GetTokenData() *TokenData { + if x != nil { + return x.TokenData + } + return nil +} + +type GaiaPairingRequestContainer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PairingAttemptID string `protobuf:"bytes,1,opt,name=pairingAttemptID,proto3" json:"pairingAttemptID,omitempty"` + BrowserDetails *BrowserDetails `protobuf:"bytes,2,opt,name=browserDetails,proto3" json:"browserDetails,omitempty"` + StartTimestamp int64 `protobuf:"varint,3,opt,name=startTimestamp,proto3" json:"startTimestamp,omitempty"` + Data []byte `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *GaiaPairingRequestContainer) Reset() { + *x = GaiaPairingRequestContainer{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GaiaPairingRequestContainer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GaiaPairingRequestContainer) ProtoMessage() {} + +func (x *GaiaPairingRequestContainer) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GaiaPairingRequestContainer.ProtoReflect.Descriptor instead. +func (*GaiaPairingRequestContainer) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{5} +} + +func (x *GaiaPairingRequestContainer) GetPairingAttemptID() string { + if x != nil { + return x.PairingAttemptID + } + return "" +} + +func (x *GaiaPairingRequestContainer) GetBrowserDetails() *BrowserDetails { + if x != nil { + return x.BrowserDetails + } + return nil +} + +func (x *GaiaPairingRequestContainer) GetStartTimestamp() int64 { + if x != nil { + return x.StartTimestamp + } + return 0 +} + +func (x *GaiaPairingRequestContainer) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type GaiaPairingResponseContainer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FinishErrorType int32 `protobuf:"varint,1,opt,name=finishErrorType,proto3" json:"finishErrorType,omitempty"` + FinishErrorCode int32 `protobuf:"varint,2,opt,name=finishErrorCode,proto3" json:"finishErrorCode,omitempty"` + UnknownInt3 int32 `protobuf:"varint,3,opt,name=unknownInt3,proto3" json:"unknownInt3,omitempty"` // For init, 1 + SessionUUID string `protobuf:"bytes,4,opt,name=sessionUUID,proto3" json:"sessionUUID,omitempty"` + Data []byte `protobuf:"bytes,5,opt,name=data,proto3" json:"data,omitempty"` +} + +func (x *GaiaPairingResponseContainer) Reset() { + *x = GaiaPairingResponseContainer{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GaiaPairingResponseContainer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GaiaPairingResponseContainer) ProtoMessage() {} + +func (x *GaiaPairingResponseContainer) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GaiaPairingResponseContainer.ProtoReflect.Descriptor instead. +func (*GaiaPairingResponseContainer) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{6} +} + +func (x *GaiaPairingResponseContainer) GetFinishErrorType() int32 { + if x != nil { + return x.FinishErrorType + } + return 0 +} + +func (x *GaiaPairingResponseContainer) GetFinishErrorCode() int32 { + if x != nil { + return x.FinishErrorCode + } + return 0 +} + +func (x *GaiaPairingResponseContainer) GetUnknownInt3() int32 { + if x != nil { + return x.UnknownInt3 + } + return 0 +} + +func (x *GaiaPairingResponseContainer) GetSessionUUID() string { + if x != nil { + return x.SessionUUID + } + return "" +} + +func (x *GaiaPairingResponseContainer) GetData() []byte { + if x != nil { + return x.Data + } + return nil +} + +type RevokeGaiaPairingRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PairingAttemptID string `protobuf:"bytes,1,opt,name=pairingAttemptID,proto3" json:"pairingAttemptID,omitempty"` +} + +func (x *RevokeGaiaPairingRequest) Reset() { + *x = RevokeGaiaPairingRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RevokeGaiaPairingRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RevokeGaiaPairingRequest) ProtoMessage() {} + +func (x *RevokeGaiaPairingRequest) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RevokeGaiaPairingRequest.ProtoReflect.Descriptor instead. +func (*RevokeGaiaPairingRequest) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{7} +} + +func (x *RevokeGaiaPairingRequest) GetPairingAttemptID() string { + if x != nil { + return x.PairingAttemptID + } + return "" +} + +type RPCGaiaData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Command int32 `protobuf:"varint,1,opt,name=command,proto3" json:"command,omitempty"` // 9 + MaybeServerData *RPCGaiaData_UnknownContainer `protobuf:"bytes,108,opt,name=maybeServerData,proto3" json:"maybeServerData,omitempty"` +} + +func (x *RPCGaiaData) Reset() { + *x = RPCGaiaData{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RPCGaiaData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RPCGaiaData) ProtoMessage() {} + +func (x *RPCGaiaData) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RPCGaiaData.ProtoReflect.Descriptor instead. +func (*RPCGaiaData) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{8} +} + +func (x *RPCGaiaData) GetCommand() int32 { + if x != nil { + return x.Command + } + return 0 +} + +func (x *RPCGaiaData) GetMaybeServerData() *RPCGaiaData_UnknownContainer { + if x != nil { + return x.MaybeServerData + } + return nil +} + type AuthenticationContainer struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -368,7 +762,7 @@ type AuthenticationContainer struct { func (x *AuthenticationContainer) Reset() { *x = AuthenticationContainer{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[3] + mi := &file_authentication_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -381,7 +775,7 @@ func (x *AuthenticationContainer) String() string { func (*AuthenticationContainer) ProtoMessage() {} func (x *AuthenticationContainer) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[3] + mi := &file_authentication_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -394,7 +788,7 @@ func (x *AuthenticationContainer) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthenticationContainer.ProtoReflect.Descriptor instead. func (*AuthenticationContainer) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{3} + return file_authentication_proto_rawDescGZIP(), []int{9} } func (x *AuthenticationContainer) GetAuthMessage() *AuthMessage { @@ -454,15 +848,15 @@ type AuthMessage struct { unknownFields protoimpl.UnknownFields RequestID string `protobuf:"bytes,1,opt,name=requestID,proto3" json:"requestID,omitempty"` - Network *string `protobuf:"bytes,3,opt,name=network,proto3,oneof" json:"network,omitempty"` - TachyonAuthToken []byte `protobuf:"bytes,6,opt,name=tachyonAuthToken,proto3,oneof" json:"tachyonAuthToken,omitempty"` + Network string `protobuf:"bytes,3,opt,name=network,proto3" json:"network,omitempty"` + TachyonAuthToken []byte `protobuf:"bytes,6,opt,name=tachyonAuthToken,proto3" json:"tachyonAuthToken,omitempty"` ConfigVersion *ConfigVersion `protobuf:"bytes,7,opt,name=configVersion,proto3" json:"configVersion,omitempty"` } func (x *AuthMessage) Reset() { *x = AuthMessage{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[4] + mi := &file_authentication_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -475,7 +869,7 @@ func (x *AuthMessage) String() string { func (*AuthMessage) ProtoMessage() {} func (x *AuthMessage) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[4] + mi := &file_authentication_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -488,7 +882,7 @@ func (x *AuthMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use AuthMessage.ProtoReflect.Descriptor instead. func (*AuthMessage) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{4} + return file_authentication_proto_rawDescGZIP(), []int{10} } func (x *AuthMessage) GetRequestID() string { @@ -499,8 +893,8 @@ func (x *AuthMessage) GetRequestID() string { } func (x *AuthMessage) GetNetwork() string { - if x != nil && x.Network != nil { - return *x.Network + if x != nil { + return x.Network } return "" } @@ -531,7 +925,7 @@ type RevokeRelayPairingRequest struct { func (x *RevokeRelayPairingRequest) Reset() { *x = RevokeRelayPairingRequest{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[5] + mi := &file_authentication_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -544,7 +938,7 @@ func (x *RevokeRelayPairingRequest) String() string { func (*RevokeRelayPairingRequest) ProtoMessage() {} func (x *RevokeRelayPairingRequest) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[5] + mi := &file_authentication_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -557,7 +951,7 @@ func (x *RevokeRelayPairingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RevokeRelayPairingRequest.ProtoReflect.Descriptor instead. func (*RevokeRelayPairingRequest) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{5} + return file_authentication_proto_rawDescGZIP(), []int{11} } func (x *RevokeRelayPairingRequest) GetAuthMessage() *AuthMessage { @@ -583,7 +977,7 @@ type RevokeRelayPairingResponse struct { func (x *RevokeRelayPairingResponse) Reset() { *x = RevokeRelayPairingResponse{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[6] + mi := &file_authentication_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -596,7 +990,7 @@ func (x *RevokeRelayPairingResponse) String() string { func (*RevokeRelayPairingResponse) ProtoMessage() {} func (x *RevokeRelayPairingResponse) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[6] + mi := &file_authentication_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -609,7 +1003,7 @@ func (x *RevokeRelayPairingResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RevokeRelayPairingResponse.ProtoReflect.Descriptor instead. func (*RevokeRelayPairingResponse) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{6} + return file_authentication_proto_rawDescGZIP(), []int{12} } type RegisterRefreshRequest struct { @@ -628,7 +1022,7 @@ type RegisterRefreshRequest struct { func (x *RegisterRefreshRequest) Reset() { *x = RegisterRefreshRequest{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[7] + mi := &file_authentication_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -641,7 +1035,7 @@ func (x *RegisterRefreshRequest) String() string { func (*RegisterRefreshRequest) ProtoMessage() {} func (x *RegisterRefreshRequest) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[7] + mi := &file_authentication_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -654,7 +1048,7 @@ func (x *RegisterRefreshRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterRefreshRequest.ProtoReflect.Descriptor instead. func (*RegisterRefreshRequest) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{7} + return file_authentication_proto_rawDescGZIP(), []int{13} } func (x *RegisterRefreshRequest) GetMessageAuth() *AuthMessage { @@ -704,13 +1098,13 @@ type RegisterRefreshResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - TokenData *RegisterRefreshResponse_AuthKeyData `protobuf:"bytes,2,opt,name=tokenData,proto3" json:"tokenData,omitempty"` + TokenData *TokenData `protobuf:"bytes,2,opt,name=tokenData,proto3" json:"tokenData,omitempty"` } func (x *RegisterRefreshResponse) Reset() { *x = RegisterRefreshResponse{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[8] + mi := &file_authentication_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -723,7 +1117,7 @@ func (x *RegisterRefreshResponse) String() string { func (*RegisterRefreshResponse) ProtoMessage() {} func (x *RegisterRefreshResponse) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[8] + mi := &file_authentication_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -736,10 +1130,10 @@ func (x *RegisterRefreshResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterRefreshResponse.ProtoReflect.Descriptor instead. func (*RegisterRefreshResponse) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{8} + return file_authentication_proto_rawDescGZIP(), []int{14} } -func (x *RegisterRefreshResponse) GetTokenData() *RegisterRefreshResponse_AuthKeyData { +func (x *RegisterRefreshResponse) GetTokenData() *TokenData { if x != nil { return x.TokenData } @@ -751,18 +1145,18 @@ type RegisterPhoneRelayResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Coordinates *CoordinateMessage `protobuf:"bytes,1,opt,name=coordinates,proto3" json:"coordinates,omitempty"` - Browser *Device `protobuf:"bytes,2,opt,name=browser,proto3" json:"browser,omitempty"` - PairingKey []byte `protobuf:"bytes,3,opt,name=pairingKey,proto3" json:"pairingKey,omitempty"` - ValidFor int64 `protobuf:"varint,4,opt,name=validFor,proto3" json:"validFor,omitempty"` - AuthKeyData *RegisterPhoneRelayResponse_AuthKeyData `protobuf:"bytes,5,opt,name=authKeyData,proto3" json:"authKeyData,omitempty"` - ResponseID string `protobuf:"bytes,6,opt,name=responseID,proto3" json:"responseID,omitempty"` + Coordinates *CoordinateMessage `protobuf:"bytes,1,opt,name=coordinates,proto3" json:"coordinates,omitempty"` + Browser *Device `protobuf:"bytes,2,opt,name=browser,proto3" json:"browser,omitempty"` + PairingKey []byte `protobuf:"bytes,3,opt,name=pairingKey,proto3" json:"pairingKey,omitempty"` + ValidFor int64 `protobuf:"varint,4,opt,name=validFor,proto3" json:"validFor,omitempty"` + AuthKeyData *TokenData `protobuf:"bytes,5,opt,name=authKeyData,proto3" json:"authKeyData,omitempty"` + ResponseID string `protobuf:"bytes,6,opt,name=responseID,proto3" json:"responseID,omitempty"` } func (x *RegisterPhoneRelayResponse) Reset() { *x = RegisterPhoneRelayResponse{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[9] + mi := &file_authentication_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -775,7 +1169,7 @@ func (x *RegisterPhoneRelayResponse) String() string { func (*RegisterPhoneRelayResponse) ProtoMessage() {} func (x *RegisterPhoneRelayResponse) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[9] + mi := &file_authentication_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -788,7 +1182,7 @@ func (x *RegisterPhoneRelayResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RegisterPhoneRelayResponse.ProtoReflect.Descriptor instead. func (*RegisterPhoneRelayResponse) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{9} + return file_authentication_proto_rawDescGZIP(), []int{15} } func (x *RegisterPhoneRelayResponse) GetCoordinates() *CoordinateMessage { @@ -819,7 +1213,7 @@ func (x *RegisterPhoneRelayResponse) GetValidFor() int64 { return 0 } -func (x *RegisterPhoneRelayResponse) GetAuthKeyData() *RegisterPhoneRelayResponse_AuthKeyData { +func (x *RegisterPhoneRelayResponse) GetAuthKeyData() *TokenData { if x != nil { return x.AuthKeyData } @@ -844,7 +1238,7 @@ type CoordinateMessage struct { func (x *CoordinateMessage) Reset() { *x = CoordinateMessage{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[10] + mi := &file_authentication_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -857,7 +1251,7 @@ func (x *CoordinateMessage) String() string { func (*CoordinateMessage) ProtoMessage() {} func (x *CoordinateMessage) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[10] + mi := &file_authentication_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -870,7 +1264,7 @@ func (x *CoordinateMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use CoordinateMessage.ProtoReflect.Descriptor instead. func (*CoordinateMessage) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{10} + return file_authentication_proto_rawDescGZIP(), []int{16} } func (x *CoordinateMessage) GetCoord1() int64 { @@ -893,7 +1287,7 @@ type RefreshPhoneRelayResponse struct { func (x *RefreshPhoneRelayResponse) Reset() { *x = RefreshPhoneRelayResponse{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[11] + mi := &file_authentication_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -906,7 +1300,7 @@ func (x *RefreshPhoneRelayResponse) String() string { func (*RefreshPhoneRelayResponse) ProtoMessage() {} func (x *RefreshPhoneRelayResponse) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[11] + mi := &file_authentication_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -919,7 +1313,7 @@ func (x *RefreshPhoneRelayResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RefreshPhoneRelayResponse.ProtoReflect.Descriptor instead. func (*RefreshPhoneRelayResponse) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{11} + return file_authentication_proto_rawDescGZIP(), []int{17} } func (x *RefreshPhoneRelayResponse) GetCoordinates() *CoordinateMessage { @@ -955,7 +1349,7 @@ type WebEncryptionKeyResponse struct { func (x *WebEncryptionKeyResponse) Reset() { *x = WebEncryptionKeyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[12] + mi := &file_authentication_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -968,7 +1362,7 @@ func (x *WebEncryptionKeyResponse) String() string { func (*WebEncryptionKeyResponse) ProtoMessage() {} func (x *WebEncryptionKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[12] + mi := &file_authentication_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -981,7 +1375,7 @@ func (x *WebEncryptionKeyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use WebEncryptionKeyResponse.ProtoReflect.Descriptor instead. func (*WebEncryptionKeyResponse) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{12} + return file_authentication_proto_rawDescGZIP(), []int{18} } func (x *WebEncryptionKeyResponse) GetCoordinates() *CoordinateMessage { @@ -1011,7 +1405,7 @@ type ErrorResponse struct { func (x *ErrorResponse) Reset() { *x = ErrorResponse{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[13] + mi := &file_authentication_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1024,7 +1418,7 @@ func (x *ErrorResponse) String() string { func (*ErrorResponse) ProtoMessage() {} func (x *ErrorResponse) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[13] + mi := &file_authentication_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1037,7 +1431,7 @@ func (x *ErrorResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ErrorResponse.ProtoReflect.Descriptor instead. func (*ErrorResponse) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{13} + return file_authentication_proto_rawDescGZIP(), []int{19} } func (x *ErrorResponse) GetType() int64 { @@ -1073,7 +1467,7 @@ type ECDSAKeys struct { func (x *ECDSAKeys) Reset() { *x = ECDSAKeys{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[14] + mi := &file_authentication_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1086,7 +1480,7 @@ func (x *ECDSAKeys) String() string { func (*ECDSAKeys) ProtoMessage() {} func (x *ECDSAKeys) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[14] + mi := &file_authentication_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1099,7 +1493,7 @@ func (x *ECDSAKeys) ProtoReflect() protoreflect.Message { // Deprecated: Use ECDSAKeys.ProtoReflect.Descriptor instead. func (*ECDSAKeys) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{14} + return file_authentication_proto_rawDescGZIP(), []int{20} } func (x *ECDSAKeys) GetField1() int64 { @@ -1127,7 +1521,7 @@ type CurrentDeviceData struct { func (x *CurrentDeviceData) Reset() { *x = CurrentDeviceData{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[15] + mi := &file_authentication_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1140,7 +1534,7 @@ func (x *CurrentDeviceData) String() string { func (*CurrentDeviceData) ProtoMessage() {} func (x *CurrentDeviceData) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[15] + mi := &file_authentication_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1153,7 +1547,7 @@ func (x *CurrentDeviceData) ProtoReflect() protoreflect.Message { // Deprecated: Use CurrentDeviceData.ProtoReflect.Descriptor instead. func (*CurrentDeviceData) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{15} + return file_authentication_proto_rawDescGZIP(), []int{21} } func (x *CurrentDeviceData) GetBrowser() *Device { @@ -1177,7 +1571,7 @@ type KeyData struct { func (x *KeyData) Reset() { *x = KeyData{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[16] + mi := &file_authentication_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1190,7 +1584,7 @@ func (x *KeyData) String() string { func (*KeyData) ProtoMessage() {} func (x *KeyData) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[16] + mi := &file_authentication_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1203,7 +1597,7 @@ func (x *KeyData) ProtoReflect() protoreflect.Message { // Deprecated: Use KeyData.ProtoReflect.Descriptor instead. func (*KeyData) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{16} + return file_authentication_proto_rawDescGZIP(), []int{22} } func (x *KeyData) GetMobile() *Device { @@ -1246,7 +1640,7 @@ type WebAuthKey struct { func (x *WebAuthKey) Reset() { *x = WebAuthKey{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[17] + mi := &file_authentication_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1259,7 +1653,7 @@ func (x *WebAuthKey) String() string { func (*WebAuthKey) ProtoMessage() {} func (x *WebAuthKey) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[17] + mi := &file_authentication_proto_msgTypes[23] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1272,7 +1666,7 @@ func (x *WebAuthKey) ProtoReflect() protoreflect.Message { // Deprecated: Use WebAuthKey.ProtoReflect.Descriptor instead. func (*WebAuthKey) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{17} + return file_authentication_proto_rawDescGZIP(), []int{23} } func (x *WebAuthKey) GetWebAuthKey() []byte { @@ -1302,7 +1696,7 @@ type URLData struct { func (x *URLData) Reset() { *x = URLData{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[18] + mi := &file_authentication_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1315,7 +1709,7 @@ func (x *URLData) String() string { func (*URLData) ProtoMessage() {} func (x *URLData) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[18] + mi := &file_authentication_proto_msgTypes[24] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1328,7 +1722,7 @@ func (x *URLData) ProtoReflect() protoreflect.Message { // Deprecated: Use URLData.ProtoReflect.Descriptor instead. func (*URLData) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{18} + return file_authentication_proto_rawDescGZIP(), []int{24} } func (x *URLData) GetPairingKey() []byte { @@ -1364,7 +1758,7 @@ type TokenData struct { func (x *TokenData) Reset() { *x = TokenData{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[19] + mi := &file_authentication_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1377,7 +1771,7 @@ func (x *TokenData) String() string { func (*TokenData) ProtoMessage() {} func (x *TokenData) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[19] + mi := &file_authentication_proto_msgTypes[25] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1390,7 +1784,7 @@ func (x *TokenData) ProtoReflect() protoreflect.Message { // Deprecated: Use TokenData.ProtoReflect.Descriptor instead. func (*TokenData) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{19} + return file_authentication_proto_rawDescGZIP(), []int{25} } func (x *TokenData) GetTachyonAuthToken() []byte { @@ -1420,7 +1814,7 @@ type PairedData struct { func (x *PairedData) Reset() { *x = PairedData{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[20] + mi := &file_authentication_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1433,7 +1827,7 @@ func (x *PairedData) String() string { func (*PairedData) ProtoMessage() {} func (x *PairedData) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[20] + mi := &file_authentication_proto_msgTypes[26] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1446,7 +1840,7 @@ func (x *PairedData) ProtoReflect() protoreflect.Message { // Deprecated: Use PairedData.ProtoReflect.Descriptor instead. func (*PairedData) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{20} + return file_authentication_proto_rawDescGZIP(), []int{26} } func (x *PairedData) GetMobile() *Device { @@ -1481,7 +1875,7 @@ type RevokePairData struct { func (x *RevokePairData) Reset() { *x = RevokePairData{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[21] + mi := &file_authentication_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1494,7 +1888,7 @@ func (x *RevokePairData) String() string { func (*RevokePairData) ProtoMessage() {} func (x *RevokePairData) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[21] + mi := &file_authentication_proto_msgTypes[27] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1507,7 +1901,7 @@ func (x *RevokePairData) ProtoReflect() protoreflect.Message { // Deprecated: Use RevokePairData.ProtoReflect.Descriptor instead. func (*RevokePairData) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{21} + return file_authentication_proto_rawDescGZIP(), []int{27} } func (x *RevokePairData) GetRevokedDevice() *Device { @@ -1517,6 +1911,651 @@ func (x *RevokePairData) GetRevokedDevice() *Device { return nil } +type SignInGaiaRequest_Inner struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DeviceID *SignInGaiaRequest_Inner_DeviceID `protobuf:"bytes,1,opt,name=deviceID,proto3" json:"deviceID,omitempty"` + SomeData *SignInGaiaRequest_Inner_Data `protobuf:"bytes,36,opt,name=someData,proto3" json:"someData,omitempty"` +} + +func (x *SignInGaiaRequest_Inner) Reset() { + *x = SignInGaiaRequest_Inner{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignInGaiaRequest_Inner) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignInGaiaRequest_Inner) ProtoMessage() {} + +func (x *SignInGaiaRequest_Inner) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignInGaiaRequest_Inner.ProtoReflect.Descriptor instead. +func (*SignInGaiaRequest_Inner) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{3, 0} +} + +func (x *SignInGaiaRequest_Inner) GetDeviceID() *SignInGaiaRequest_Inner_DeviceID { + if x != nil { + return x.DeviceID + } + return nil +} + +func (x *SignInGaiaRequest_Inner) GetSomeData() *SignInGaiaRequest_Inner_Data { + if x != nil { + return x.SomeData + } + return nil +} + +type SignInGaiaRequest_Inner_DeviceID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UnknownInt1 int32 `protobuf:"varint,1,opt,name=unknownInt1,proto3" json:"unknownInt1,omitempty"` // 3 + DeviceID string `protobuf:"bytes,2,opt,name=deviceID,proto3" json:"deviceID,omitempty"` // messages-web-{uuid without dashes} +} + +func (x *SignInGaiaRequest_Inner_DeviceID) Reset() { + *x = SignInGaiaRequest_Inner_DeviceID{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignInGaiaRequest_Inner_DeviceID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignInGaiaRequest_Inner_DeviceID) ProtoMessage() {} + +func (x *SignInGaiaRequest_Inner_DeviceID) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignInGaiaRequest_Inner_DeviceID.ProtoReflect.Descriptor instead. +func (*SignInGaiaRequest_Inner_DeviceID) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{3, 0, 0} +} + +func (x *SignInGaiaRequest_Inner_DeviceID) GetUnknownInt1() int32 { + if x != nil { + return x.UnknownInt1 + } + return 0 +} + +func (x *SignInGaiaRequest_Inner_DeviceID) GetDeviceID() string { + if x != nil { + return x.DeviceID + } + return "" +} + +type SignInGaiaRequest_Inner_Data struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SomeData []byte `protobuf:"bytes,3,opt,name=someData,proto3" json:"someData,omitempty"` // maybe an encryption key? +} + +func (x *SignInGaiaRequest_Inner_Data) Reset() { + *x = SignInGaiaRequest_Inner_Data{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignInGaiaRequest_Inner_Data) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignInGaiaRequest_Inner_Data) ProtoMessage() {} + +func (x *SignInGaiaRequest_Inner_Data) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[30] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignInGaiaRequest_Inner_Data.ProtoReflect.Descriptor instead. +func (*SignInGaiaRequest_Inner_Data) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{3, 0, 1} +} + +func (x *SignInGaiaRequest_Inner_Data) GetSomeData() []byte { + if x != nil { + return x.SomeData + } + return nil +} + +type SignInGaiaResponse_Header struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UnknownInt2 uint64 `protobuf:"varint,2,opt,name=unknownInt2,proto3" json:"unknownInt2,omitempty"` + UnknownTimestamp int64 `protobuf:"varint,4,opt,name=unknownTimestamp,proto3" json:"unknownTimestamp,omitempty"` +} + +func (x *SignInGaiaResponse_Header) Reset() { + *x = SignInGaiaResponse_Header{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignInGaiaResponse_Header) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignInGaiaResponse_Header) ProtoMessage() {} + +func (x *SignInGaiaResponse_Header) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[31] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignInGaiaResponse_Header.ProtoReflect.Descriptor instead. +func (*SignInGaiaResponse_Header) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{4, 0} +} + +func (x *SignInGaiaResponse_Header) GetUnknownInt2() uint64 { + if x != nil { + return x.UnknownInt2 + } + return 0 +} + +func (x *SignInGaiaResponse_Header) GetUnknownTimestamp() int64 { + if x != nil { + return x.UnknownTimestamp + } + return 0 +} + +type SignInGaiaResponse_DeviceData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DeviceWrapper *SignInGaiaResponse_DeviceData_DeviceWrapper `protobuf:"bytes,1,opt,name=deviceWrapper,proto3" json:"deviceWrapper,omitempty"` + UnknownItems2 []*RPCGaiaData_UnknownContainer_Item2_Item1 `protobuf:"bytes,2,rep,name=unknownItems2,proto3" json:"unknownItems2,omitempty"` + UnknownItems3 []*RPCGaiaData_UnknownContainer_Item4 `protobuf:"bytes,3,rep,name=unknownItems3,proto3" json:"unknownItems3,omitempty"` // index 4 is some unknown field with no real data +} + +func (x *SignInGaiaResponse_DeviceData) Reset() { + *x = SignInGaiaResponse_DeviceData{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignInGaiaResponse_DeviceData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignInGaiaResponse_DeviceData) ProtoMessage() {} + +func (x *SignInGaiaResponse_DeviceData) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[32] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignInGaiaResponse_DeviceData.ProtoReflect.Descriptor instead. +func (*SignInGaiaResponse_DeviceData) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{4, 1} +} + +func (x *SignInGaiaResponse_DeviceData) GetDeviceWrapper() *SignInGaiaResponse_DeviceData_DeviceWrapper { + if x != nil { + return x.DeviceWrapper + } + return nil +} + +func (x *SignInGaiaResponse_DeviceData) GetUnknownItems2() []*RPCGaiaData_UnknownContainer_Item2_Item1 { + if x != nil { + return x.UnknownItems2 + } + return nil +} + +func (x *SignInGaiaResponse_DeviceData) GetUnknownItems3() []*RPCGaiaData_UnknownContainer_Item4 { + if x != nil { + return x.UnknownItems3 + } + return nil +} + +type SignInGaiaResponse_DeviceData_DeviceWrapper struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Device *Device `protobuf:"bytes,1,opt,name=device,proto3" json:"device,omitempty"` +} + +func (x *SignInGaiaResponse_DeviceData_DeviceWrapper) Reset() { + *x = SignInGaiaResponse_DeviceData_DeviceWrapper{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[33] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SignInGaiaResponse_DeviceData_DeviceWrapper) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SignInGaiaResponse_DeviceData_DeviceWrapper) ProtoMessage() {} + +func (x *SignInGaiaResponse_DeviceData_DeviceWrapper) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[33] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SignInGaiaResponse_DeviceData_DeviceWrapper.ProtoReflect.Descriptor instead. +func (*SignInGaiaResponse_DeviceData_DeviceWrapper) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{4, 1, 0} +} + +func (x *SignInGaiaResponse_DeviceData_DeviceWrapper) GetDevice() *Device { + if x != nil { + return x.Device + } + return nil +} + +type RPCGaiaData_UnknownContainer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item2 *RPCGaiaData_UnknownContainer_Item2 `protobuf:"bytes,2,opt,name=item2,proto3" json:"item2,omitempty"` + UnknownTimestampMicroseconds int64 `protobuf:"varint,3,opt,name=unknownTimestampMicroseconds,proto3" json:"unknownTimestampMicroseconds,omitempty"` // pairing timestamp? + Item4 []*RPCGaiaData_UnknownContainer_Item4 `protobuf:"bytes,4,rep,name=item4,proto3" json:"item4,omitempty"` +} + +func (x *RPCGaiaData_UnknownContainer) Reset() { + *x = RPCGaiaData_UnknownContainer{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[34] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RPCGaiaData_UnknownContainer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RPCGaiaData_UnknownContainer) ProtoMessage() {} + +func (x *RPCGaiaData_UnknownContainer) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[34] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RPCGaiaData_UnknownContainer.ProtoReflect.Descriptor instead. +func (*RPCGaiaData_UnknownContainer) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{8, 0} +} + +func (x *RPCGaiaData_UnknownContainer) GetItem2() *RPCGaiaData_UnknownContainer_Item2 { + if x != nil { + return x.Item2 + } + return nil +} + +func (x *RPCGaiaData_UnknownContainer) GetUnknownTimestampMicroseconds() int64 { + if x != nil { + return x.UnknownTimestampMicroseconds + } + return 0 +} + +func (x *RPCGaiaData_UnknownContainer) GetItem4() []*RPCGaiaData_UnknownContainer_Item4 { + if x != nil { + return x.Item4 + } + return nil +} + +type RPCGaiaData_UnknownContainer_Item2 struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item1 []*RPCGaiaData_UnknownContainer_Item2_Item1 `protobuf:"bytes,1,rep,name=item1,proto3" json:"item1,omitempty"` +} + +func (x *RPCGaiaData_UnknownContainer_Item2) Reset() { + *x = RPCGaiaData_UnknownContainer_Item2{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[35] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RPCGaiaData_UnknownContainer_Item2) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RPCGaiaData_UnknownContainer_Item2) ProtoMessage() {} + +func (x *RPCGaiaData_UnknownContainer_Item2) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[35] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RPCGaiaData_UnknownContainer_Item2.ProtoReflect.Descriptor instead. +func (*RPCGaiaData_UnknownContainer_Item2) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{8, 0, 0} +} + +func (x *RPCGaiaData_UnknownContainer_Item2) GetItem1() []*RPCGaiaData_UnknownContainer_Item2_Item1 { + if x != nil { + return x.Item1 + } + return nil +} + +type RPCGaiaData_UnknownContainer_Item4 struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DestOrSourceUUID string `protobuf:"bytes,1,opt,name=destOrSourceUUID,proto3" json:"destOrSourceUUID,omitempty"` + UnknownInt3 int32 `protobuf:"varint,3,opt,name=unknownInt3,proto3" json:"unknownInt3,omitempty"` // 1 for destination device, 6 for local device? + UnknownInt4 int32 `protobuf:"varint,4,opt,name=unknownInt4,proto3" json:"unknownInt4,omitempty"` // always 6? + UnknownTimestampMicroseconds int64 `protobuf:"varint,7,opt,name=unknownTimestampMicroseconds,proto3" json:"unknownTimestampMicroseconds,omitempty"` // maybe device creation ts? + Item8 *RPCGaiaData_UnknownContainer_Item4_Item8 `protobuf:"bytes,8,opt,name=item8,proto3" json:"item8,omitempty"` +} + +func (x *RPCGaiaData_UnknownContainer_Item4) Reset() { + *x = RPCGaiaData_UnknownContainer_Item4{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[36] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RPCGaiaData_UnknownContainer_Item4) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RPCGaiaData_UnknownContainer_Item4) ProtoMessage() {} + +func (x *RPCGaiaData_UnknownContainer_Item4) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[36] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RPCGaiaData_UnknownContainer_Item4.ProtoReflect.Descriptor instead. +func (*RPCGaiaData_UnknownContainer_Item4) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{8, 0, 1} +} + +func (x *RPCGaiaData_UnknownContainer_Item4) GetDestOrSourceUUID() string { + if x != nil { + return x.DestOrSourceUUID + } + return "" +} + +func (x *RPCGaiaData_UnknownContainer_Item4) GetUnknownInt3() int32 { + if x != nil { + return x.UnknownInt3 + } + return 0 +} + +func (x *RPCGaiaData_UnknownContainer_Item4) GetUnknownInt4() int32 { + if x != nil { + return x.UnknownInt4 + } + return 0 +} + +func (x *RPCGaiaData_UnknownContainer_Item4) GetUnknownTimestampMicroseconds() int64 { + if x != nil { + return x.UnknownTimestampMicroseconds + } + return 0 +} + +func (x *RPCGaiaData_UnknownContainer_Item4) GetItem8() *RPCGaiaData_UnknownContainer_Item4_Item8 { + if x != nil { + return x.Item8 + } + return nil +} + +type RPCGaiaData_UnknownContainer_Item2_Item1 struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DestOrSourceUUID string `protobuf:"bytes,1,opt,name=destOrSourceUUID,proto3" json:"destOrSourceUUID,omitempty"` + UnknownInt4 int32 `protobuf:"varint,4,opt,name=unknownInt4,proto3" json:"unknownInt4,omitempty"` // 1 for destination device, 6 for local device? + LanguageCode string `protobuf:"bytes,5,opt,name=languageCode,proto3" json:"languageCode,omitempty"` + UnknownBigInt7 uint64 `protobuf:"varint,7,opt,name=unknownBigInt7,proto3" json:"unknownBigInt7,omitempty"` +} + +func (x *RPCGaiaData_UnknownContainer_Item2_Item1) Reset() { + *x = RPCGaiaData_UnknownContainer_Item2_Item1{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[37] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RPCGaiaData_UnknownContainer_Item2_Item1) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RPCGaiaData_UnknownContainer_Item2_Item1) ProtoMessage() {} + +func (x *RPCGaiaData_UnknownContainer_Item2_Item1) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[37] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RPCGaiaData_UnknownContainer_Item2_Item1.ProtoReflect.Descriptor instead. +func (*RPCGaiaData_UnknownContainer_Item2_Item1) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{8, 0, 0, 0} +} + +func (x *RPCGaiaData_UnknownContainer_Item2_Item1) GetDestOrSourceUUID() string { + if x != nil { + return x.DestOrSourceUUID + } + return "" +} + +func (x *RPCGaiaData_UnknownContainer_Item2_Item1) GetUnknownInt4() int32 { + if x != nil { + return x.UnknownInt4 + } + return 0 +} + +func (x *RPCGaiaData_UnknownContainer_Item2_Item1) GetLanguageCode() string { + if x != nil { + return x.LanguageCode + } + return "" +} + +func (x *RPCGaiaData_UnknownContainer_Item2_Item1) GetUnknownBigInt7() uint64 { + if x != nil { + return x.UnknownBigInt7 + } + return 0 +} + +type RPCGaiaData_UnknownContainer_Item4_Item8 struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UnknownInt1 int32 `protobuf:"varint,1,opt,name=unknownInt1,proto3" json:"unknownInt1,omitempty"` // present for destination device? + UnknownTimestamp int32 `protobuf:"varint,2,opt,name=unknownTimestamp,proto3" json:"unknownTimestamp,omitempty"` // present for destination device? + UnknownBytes []byte `protobuf:"bytes,3,opt,name=unknownBytes,proto3" json:"unknownBytes,omitempty"` // present for local device? +} + +func (x *RPCGaiaData_UnknownContainer_Item4_Item8) Reset() { + *x = RPCGaiaData_UnknownContainer_Item4_Item8{} + if protoimpl.UnsafeEnabled { + mi := &file_authentication_proto_msgTypes[38] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RPCGaiaData_UnknownContainer_Item4_Item8) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RPCGaiaData_UnknownContainer_Item4_Item8) ProtoMessage() {} + +func (x *RPCGaiaData_UnknownContainer_Item4_Item8) ProtoReflect() protoreflect.Message { + mi := &file_authentication_proto_msgTypes[38] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RPCGaiaData_UnknownContainer_Item4_Item8.ProtoReflect.Descriptor instead. +func (*RPCGaiaData_UnknownContainer_Item4_Item8) Descriptor() ([]byte, []int) { + return file_authentication_proto_rawDescGZIP(), []int{8, 0, 1, 0} +} + +func (x *RPCGaiaData_UnknownContainer_Item4_Item8) GetUnknownInt1() int32 { + if x != nil { + return x.UnknownInt1 + } + return 0 +} + +func (x *RPCGaiaData_UnknownContainer_Item4_Item8) GetUnknownTimestamp() int32 { + if x != nil { + return x.UnknownTimestamp + } + return 0 +} + +func (x *RPCGaiaData_UnknownContainer_Item4_Item8) GetUnknownBytes() []byte { + if x != nil { + return x.UnknownBytes + } + return nil +} + type RegisterRefreshRequest_NestedEmptyArr struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1528,7 +2567,7 @@ type RegisterRefreshRequest_NestedEmptyArr struct { func (x *RegisterRefreshRequest_NestedEmptyArr) Reset() { *x = RegisterRefreshRequest_NestedEmptyArr{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[22] + mi := &file_authentication_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1541,7 +2580,7 @@ func (x *RegisterRefreshRequest_NestedEmptyArr) String() string { func (*RegisterRefreshRequest_NestedEmptyArr) ProtoMessage() {} func (x *RegisterRefreshRequest_NestedEmptyArr) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[22] + mi := &file_authentication_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1554,7 +2593,7 @@ func (x *RegisterRefreshRequest_NestedEmptyArr) ProtoReflect() protoreflect.Mess // Deprecated: Use RegisterRefreshRequest_NestedEmptyArr.ProtoReflect.Descriptor instead. func (*RegisterRefreshRequest_NestedEmptyArr) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{7, 0} + return file_authentication_proto_rawDescGZIP(), []int{13, 0} } func (x *RegisterRefreshRequest_NestedEmptyArr) GetEmptyArr() *EmptyArr { @@ -1564,116 +2603,6 @@ func (x *RegisterRefreshRequest_NestedEmptyArr) GetEmptyArr() *EmptyArr { return nil } -type RegisterRefreshResponse_AuthKeyData struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TachyonAuthToken []byte `protobuf:"bytes,1,opt,name=tachyonAuthToken,proto3" json:"tachyonAuthToken,omitempty"` - ValidFor string `protobuf:"bytes,2,opt,name=validFor,proto3" json:"validFor,omitempty"` -} - -func (x *RegisterRefreshResponse_AuthKeyData) Reset() { - *x = RegisterRefreshResponse_AuthKeyData{} - if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RegisterRefreshResponse_AuthKeyData) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RegisterRefreshResponse_AuthKeyData) ProtoMessage() {} - -func (x *RegisterRefreshResponse_AuthKeyData) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[23] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RegisterRefreshResponse_AuthKeyData.ProtoReflect.Descriptor instead. -func (*RegisterRefreshResponse_AuthKeyData) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{8, 0} -} - -func (x *RegisterRefreshResponse_AuthKeyData) GetTachyonAuthToken() []byte { - if x != nil { - return x.TachyonAuthToken - } - return nil -} - -func (x *RegisterRefreshResponse_AuthKeyData) GetValidFor() string { - if x != nil { - return x.ValidFor - } - return "" -} - -type RegisterPhoneRelayResponse_AuthKeyData struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TachyonAuthToken []byte `protobuf:"bytes,1,opt,name=tachyonAuthToken,proto3" json:"tachyonAuthToken,omitempty"` - ValidFor int64 `protobuf:"varint,2,opt,name=validFor,proto3" json:"validFor,omitempty"` -} - -func (x *RegisterPhoneRelayResponse_AuthKeyData) Reset() { - *x = RegisterPhoneRelayResponse_AuthKeyData{} - if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RegisterPhoneRelayResponse_AuthKeyData) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RegisterPhoneRelayResponse_AuthKeyData) ProtoMessage() {} - -func (x *RegisterPhoneRelayResponse_AuthKeyData) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RegisterPhoneRelayResponse_AuthKeyData.ProtoReflect.Descriptor instead. -func (*RegisterPhoneRelayResponse_AuthKeyData) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{9, 0} -} - -func (x *RegisterPhoneRelayResponse_AuthKeyData) GetTachyonAuthToken() []byte { - if x != nil { - return x.TachyonAuthToken - } - return nil -} - -func (x *RegisterPhoneRelayResponse_AuthKeyData) GetValidFor() int64 { - if x != nil { - return x.ValidFor - } - return 0 -} - type ErrorResponse_ErrorClass struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1685,7 +2614,7 @@ type ErrorResponse_ErrorClass struct { func (x *ErrorResponse_ErrorClass) Reset() { *x = ErrorResponse_ErrorClass{} if protoimpl.UnsafeEnabled { - mi := &file_authentication_proto_msgTypes[25] + mi := &file_authentication_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1698,7 +2627,7 @@ func (x *ErrorResponse_ErrorClass) String() string { func (*ErrorResponse_ErrorClass) ProtoMessage() {} func (x *ErrorResponse_ErrorClass) ProtoReflect() protoreflect.Message { - mi := &file_authentication_proto_msgTypes[25] + mi := &file_authentication_proto_msgTypes[40] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1711,7 +2640,7 @@ func (x *ErrorResponse_ErrorClass) ProtoReflect() protoreflect.Message { // Deprecated: Use ErrorResponse_ErrorClass.ProtoReflect.Descriptor instead. func (*ErrorResponse_ErrorClass) Descriptor() ([]byte, []int) { - return file_authentication_proto_rawDescGZIP(), []int{13, 0} + return file_authentication_proto_rawDescGZIP(), []int{19, 0} } func (x *ErrorResponse_ErrorClass) GetClass() string { @@ -1739,73 +2668,105 @@ func file_authentication_proto_rawDescGZIP() []byte { } var file_authentication_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_authentication_proto_msgTypes = make([]protoimpl.MessageInfo, 26) +var file_authentication_proto_msgTypes = make([]protoimpl.MessageInfo, 41) var file_authentication_proto_goTypes = []interface{}{ - (BrowserType)(0), // 0: authentication.BrowserType - (DeviceType)(0), // 1: authentication.DeviceType - (*BrowserDetails)(nil), // 2: authentication.BrowserDetails - (*Device)(nil), // 3: authentication.Device - (*ConfigVersion)(nil), // 4: authentication.ConfigVersion - (*AuthenticationContainer)(nil), // 5: authentication.AuthenticationContainer - (*AuthMessage)(nil), // 6: authentication.AuthMessage - (*RevokeRelayPairingRequest)(nil), // 7: authentication.RevokeRelayPairingRequest - (*RevokeRelayPairingResponse)(nil), // 8: authentication.RevokeRelayPairingResponse - (*RegisterRefreshRequest)(nil), // 9: authentication.RegisterRefreshRequest - (*RegisterRefreshResponse)(nil), // 10: authentication.RegisterRefreshResponse - (*RegisterPhoneRelayResponse)(nil), // 11: authentication.RegisterPhoneRelayResponse - (*CoordinateMessage)(nil), // 12: authentication.CoordinateMessage - (*RefreshPhoneRelayResponse)(nil), // 13: authentication.RefreshPhoneRelayResponse - (*WebEncryptionKeyResponse)(nil), // 14: authentication.WebEncryptionKeyResponse - (*ErrorResponse)(nil), // 15: authentication.ErrorResponse - (*ECDSAKeys)(nil), // 16: authentication.ECDSAKeys - (*CurrentDeviceData)(nil), // 17: authentication.CurrentDeviceData - (*KeyData)(nil), // 18: authentication.KeyData - (*WebAuthKey)(nil), // 19: authentication.WebAuthKey - (*URLData)(nil), // 20: authentication.URLData - (*TokenData)(nil), // 21: authentication.TokenData - (*PairedData)(nil), // 22: authentication.PairedData - (*RevokePairData)(nil), // 23: authentication.RevokePairData - (*RegisterRefreshRequest_NestedEmptyArr)(nil), // 24: authentication.RegisterRefreshRequest.NestedEmptyArr - (*RegisterRefreshResponse_AuthKeyData)(nil), // 25: authentication.RegisterRefreshResponse.AuthKeyData - (*RegisterPhoneRelayResponse_AuthKeyData)(nil), // 26: authentication.RegisterPhoneRelayResponse.AuthKeyData - (*ErrorResponse_ErrorClass)(nil), // 27: authentication.ErrorResponse.ErrorClass - (*EmptyArr)(nil), // 28: util.EmptyArr + (BrowserType)(0), // 0: authentication.BrowserType + (DeviceType)(0), // 1: authentication.DeviceType + (*BrowserDetails)(nil), // 2: authentication.BrowserDetails + (*Device)(nil), // 3: authentication.Device + (*ConfigVersion)(nil), // 4: authentication.ConfigVersion + (*SignInGaiaRequest)(nil), // 5: authentication.SignInGaiaRequest + (*SignInGaiaResponse)(nil), // 6: authentication.SignInGaiaResponse + (*GaiaPairingRequestContainer)(nil), // 7: authentication.GaiaPairingRequestContainer + (*GaiaPairingResponseContainer)(nil), // 8: authentication.GaiaPairingResponseContainer + (*RevokeGaiaPairingRequest)(nil), // 9: authentication.RevokeGaiaPairingRequest + (*RPCGaiaData)(nil), // 10: authentication.RPCGaiaData + (*AuthenticationContainer)(nil), // 11: authentication.AuthenticationContainer + (*AuthMessage)(nil), // 12: authentication.AuthMessage + (*RevokeRelayPairingRequest)(nil), // 13: authentication.RevokeRelayPairingRequest + (*RevokeRelayPairingResponse)(nil), // 14: authentication.RevokeRelayPairingResponse + (*RegisterRefreshRequest)(nil), // 15: authentication.RegisterRefreshRequest + (*RegisterRefreshResponse)(nil), // 16: authentication.RegisterRefreshResponse + (*RegisterPhoneRelayResponse)(nil), // 17: authentication.RegisterPhoneRelayResponse + (*CoordinateMessage)(nil), // 18: authentication.CoordinateMessage + (*RefreshPhoneRelayResponse)(nil), // 19: authentication.RefreshPhoneRelayResponse + (*WebEncryptionKeyResponse)(nil), // 20: authentication.WebEncryptionKeyResponse + (*ErrorResponse)(nil), // 21: authentication.ErrorResponse + (*ECDSAKeys)(nil), // 22: authentication.ECDSAKeys + (*CurrentDeviceData)(nil), // 23: authentication.CurrentDeviceData + (*KeyData)(nil), // 24: authentication.KeyData + (*WebAuthKey)(nil), // 25: authentication.WebAuthKey + (*URLData)(nil), // 26: authentication.URLData + (*TokenData)(nil), // 27: authentication.TokenData + (*PairedData)(nil), // 28: authentication.PairedData + (*RevokePairData)(nil), // 29: authentication.RevokePairData + (*SignInGaiaRequest_Inner)(nil), // 30: authentication.SignInGaiaRequest.Inner + (*SignInGaiaRequest_Inner_DeviceID)(nil), // 31: authentication.SignInGaiaRequest.Inner.DeviceID + (*SignInGaiaRequest_Inner_Data)(nil), // 32: authentication.SignInGaiaRequest.Inner.Data + (*SignInGaiaResponse_Header)(nil), // 33: authentication.SignInGaiaResponse.Header + (*SignInGaiaResponse_DeviceData)(nil), // 34: authentication.SignInGaiaResponse.DeviceData + (*SignInGaiaResponse_DeviceData_DeviceWrapper)(nil), // 35: authentication.SignInGaiaResponse.DeviceData.DeviceWrapper + (*RPCGaiaData_UnknownContainer)(nil), // 36: authentication.RPCGaiaData.UnknownContainer + (*RPCGaiaData_UnknownContainer_Item2)(nil), // 37: authentication.RPCGaiaData.UnknownContainer.Item2 + (*RPCGaiaData_UnknownContainer_Item4)(nil), // 38: authentication.RPCGaiaData.UnknownContainer.Item4 + (*RPCGaiaData_UnknownContainer_Item2_Item1)(nil), // 39: authentication.RPCGaiaData.UnknownContainer.Item2.Item1 + (*RPCGaiaData_UnknownContainer_Item4_Item8)(nil), // 40: authentication.RPCGaiaData.UnknownContainer.Item4.Item8 + (*RegisterRefreshRequest_NestedEmptyArr)(nil), // 41: authentication.RegisterRefreshRequest.NestedEmptyArr + (*ErrorResponse_ErrorClass)(nil), // 42: authentication.ErrorResponse.ErrorClass + (*EmptyArr)(nil), // 43: util.EmptyArr } var file_authentication_proto_depIdxs = []int32{ 0, // 0: authentication.BrowserDetails.browserType:type_name -> authentication.BrowserType 1, // 1: authentication.BrowserDetails.deviceType:type_name -> authentication.DeviceType - 6, // 2: authentication.AuthenticationContainer.authMessage:type_name -> authentication.AuthMessage - 2, // 3: authentication.AuthenticationContainer.browserDetails:type_name -> authentication.BrowserDetails - 18, // 4: authentication.AuthenticationContainer.keyData:type_name -> authentication.KeyData - 17, // 5: authentication.AuthenticationContainer.deviceData:type_name -> authentication.CurrentDeviceData - 4, // 6: authentication.AuthMessage.configVersion:type_name -> authentication.ConfigVersion - 6, // 7: authentication.RevokeRelayPairingRequest.authMessage:type_name -> authentication.AuthMessage - 3, // 8: authentication.RevokeRelayPairingRequest.browser:type_name -> authentication.Device - 6, // 9: authentication.RegisterRefreshRequest.messageAuth:type_name -> authentication.AuthMessage - 3, // 10: authentication.RegisterRefreshRequest.currBrowserDevice:type_name -> authentication.Device - 24, // 11: authentication.RegisterRefreshRequest.emptyRefreshArr:type_name -> authentication.RegisterRefreshRequest.NestedEmptyArr - 25, // 12: authentication.RegisterRefreshResponse.tokenData:type_name -> authentication.RegisterRefreshResponse.AuthKeyData - 12, // 13: authentication.RegisterPhoneRelayResponse.coordinates:type_name -> authentication.CoordinateMessage - 3, // 14: authentication.RegisterPhoneRelayResponse.browser:type_name -> authentication.Device - 26, // 15: authentication.RegisterPhoneRelayResponse.authKeyData:type_name -> authentication.RegisterPhoneRelayResponse.AuthKeyData - 12, // 16: authentication.RefreshPhoneRelayResponse.coordinates:type_name -> authentication.CoordinateMessage - 12, // 17: authentication.WebEncryptionKeyResponse.coordinates:type_name -> authentication.CoordinateMessage - 27, // 18: authentication.ErrorResponse.class:type_name -> authentication.ErrorResponse.ErrorClass - 3, // 19: authentication.CurrentDeviceData.browser:type_name -> authentication.Device - 3, // 20: authentication.KeyData.mobile:type_name -> authentication.Device - 16, // 21: authentication.KeyData.ecdsaKeys:type_name -> authentication.ECDSAKeys - 19, // 22: authentication.KeyData.webAuthKeyData:type_name -> authentication.WebAuthKey - 3, // 23: authentication.KeyData.browser:type_name -> authentication.Device - 3, // 24: authentication.PairedData.mobile:type_name -> authentication.Device - 21, // 25: authentication.PairedData.tokenData:type_name -> authentication.TokenData - 3, // 26: authentication.PairedData.browser:type_name -> authentication.Device - 3, // 27: authentication.RevokePairData.revokedDevice:type_name -> authentication.Device - 28, // 28: authentication.RegisterRefreshRequest.NestedEmptyArr.emptyArr:type_name -> util.EmptyArr - 29, // [29:29] is the sub-list for method output_type - 29, // [29:29] is the sub-list for method input_type - 29, // [29:29] is the sub-list for extension type_name - 29, // [29:29] is the sub-list for extension extendee - 0, // [0:29] is the sub-list for field type_name + 12, // 2: authentication.SignInGaiaRequest.authMessage:type_name -> authentication.AuthMessage + 30, // 3: authentication.SignInGaiaRequest.inner:type_name -> authentication.SignInGaiaRequest.Inner + 33, // 4: authentication.SignInGaiaResponse.header:type_name -> authentication.SignInGaiaResponse.Header + 34, // 5: authentication.SignInGaiaResponse.deviceData:type_name -> authentication.SignInGaiaResponse.DeviceData + 27, // 6: authentication.SignInGaiaResponse.tokenData:type_name -> authentication.TokenData + 2, // 7: authentication.GaiaPairingRequestContainer.browserDetails:type_name -> authentication.BrowserDetails + 36, // 8: authentication.RPCGaiaData.maybeServerData:type_name -> authentication.RPCGaiaData.UnknownContainer + 12, // 9: authentication.AuthenticationContainer.authMessage:type_name -> authentication.AuthMessage + 2, // 10: authentication.AuthenticationContainer.browserDetails:type_name -> authentication.BrowserDetails + 24, // 11: authentication.AuthenticationContainer.keyData:type_name -> authentication.KeyData + 23, // 12: authentication.AuthenticationContainer.deviceData:type_name -> authentication.CurrentDeviceData + 4, // 13: authentication.AuthMessage.configVersion:type_name -> authentication.ConfigVersion + 12, // 14: authentication.RevokeRelayPairingRequest.authMessage:type_name -> authentication.AuthMessage + 3, // 15: authentication.RevokeRelayPairingRequest.browser:type_name -> authentication.Device + 12, // 16: authentication.RegisterRefreshRequest.messageAuth:type_name -> authentication.AuthMessage + 3, // 17: authentication.RegisterRefreshRequest.currBrowserDevice:type_name -> authentication.Device + 41, // 18: authentication.RegisterRefreshRequest.emptyRefreshArr:type_name -> authentication.RegisterRefreshRequest.NestedEmptyArr + 27, // 19: authentication.RegisterRefreshResponse.tokenData:type_name -> authentication.TokenData + 18, // 20: authentication.RegisterPhoneRelayResponse.coordinates:type_name -> authentication.CoordinateMessage + 3, // 21: authentication.RegisterPhoneRelayResponse.browser:type_name -> authentication.Device + 27, // 22: authentication.RegisterPhoneRelayResponse.authKeyData:type_name -> authentication.TokenData + 18, // 23: authentication.RefreshPhoneRelayResponse.coordinates:type_name -> authentication.CoordinateMessage + 18, // 24: authentication.WebEncryptionKeyResponse.coordinates:type_name -> authentication.CoordinateMessage + 42, // 25: authentication.ErrorResponse.class:type_name -> authentication.ErrorResponse.ErrorClass + 3, // 26: authentication.CurrentDeviceData.browser:type_name -> authentication.Device + 3, // 27: authentication.KeyData.mobile:type_name -> authentication.Device + 22, // 28: authentication.KeyData.ecdsaKeys:type_name -> authentication.ECDSAKeys + 25, // 29: authentication.KeyData.webAuthKeyData:type_name -> authentication.WebAuthKey + 3, // 30: authentication.KeyData.browser:type_name -> authentication.Device + 3, // 31: authentication.PairedData.mobile:type_name -> authentication.Device + 27, // 32: authentication.PairedData.tokenData:type_name -> authentication.TokenData + 3, // 33: authentication.PairedData.browser:type_name -> authentication.Device + 3, // 34: authentication.RevokePairData.revokedDevice:type_name -> authentication.Device + 31, // 35: authentication.SignInGaiaRequest.Inner.deviceID:type_name -> authentication.SignInGaiaRequest.Inner.DeviceID + 32, // 36: authentication.SignInGaiaRequest.Inner.someData:type_name -> authentication.SignInGaiaRequest.Inner.Data + 35, // 37: authentication.SignInGaiaResponse.DeviceData.deviceWrapper:type_name -> authentication.SignInGaiaResponse.DeviceData.DeviceWrapper + 39, // 38: authentication.SignInGaiaResponse.DeviceData.unknownItems2:type_name -> authentication.RPCGaiaData.UnknownContainer.Item2.Item1 + 38, // 39: authentication.SignInGaiaResponse.DeviceData.unknownItems3:type_name -> authentication.RPCGaiaData.UnknownContainer.Item4 + 3, // 40: authentication.SignInGaiaResponse.DeviceData.DeviceWrapper.device:type_name -> authentication.Device + 37, // 41: authentication.RPCGaiaData.UnknownContainer.item2:type_name -> authentication.RPCGaiaData.UnknownContainer.Item2 + 38, // 42: authentication.RPCGaiaData.UnknownContainer.item4:type_name -> authentication.RPCGaiaData.UnknownContainer.Item4 + 39, // 43: authentication.RPCGaiaData.UnknownContainer.Item2.item1:type_name -> authentication.RPCGaiaData.UnknownContainer.Item2.Item1 + 40, // 44: authentication.RPCGaiaData.UnknownContainer.Item4.item8:type_name -> authentication.RPCGaiaData.UnknownContainer.Item4.Item8 + 43, // 45: authentication.RegisterRefreshRequest.NestedEmptyArr.emptyArr:type_name -> util.EmptyArr + 46, // [46:46] is the sub-list for method output_type + 46, // [46:46] is the sub-list for method input_type + 46, // [46:46] is the sub-list for extension type_name + 46, // [46:46] is the sub-list for extension extendee + 0, // [0:46] is the sub-list for field type_name } func init() { file_authentication_proto_init() } @@ -1814,6 +2775,7 @@ func file_authentication_proto_init() { return } file_util_proto_init() + file_pblite_proto_init() if !protoimpl.UnsafeEnabled { file_authentication_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BrowserDetails); i { @@ -1852,7 +2814,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthenticationContainer); i { + switch v := v.(*SignInGaiaRequest); i { case 0: return &v.state case 1: @@ -1864,7 +2826,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AuthMessage); i { + switch v := v.(*SignInGaiaResponse); i { case 0: return &v.state case 1: @@ -1876,7 +2838,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RevokeRelayPairingRequest); i { + switch v := v.(*GaiaPairingRequestContainer); i { case 0: return &v.state case 1: @@ -1888,7 +2850,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RevokeRelayPairingResponse); i { + switch v := v.(*GaiaPairingResponseContainer); i { case 0: return &v.state case 1: @@ -1900,7 +2862,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterRefreshRequest); i { + switch v := v.(*RevokeGaiaPairingRequest); i { case 0: return &v.state case 1: @@ -1912,7 +2874,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterRefreshResponse); i { + switch v := v.(*RPCGaiaData); i { case 0: return &v.state case 1: @@ -1924,7 +2886,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterPhoneRelayResponse); i { + switch v := v.(*AuthenticationContainer); i { case 0: return &v.state case 1: @@ -1936,7 +2898,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CoordinateMessage); i { + switch v := v.(*AuthMessage); i { case 0: return &v.state case 1: @@ -1948,7 +2910,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RefreshPhoneRelayResponse); i { + switch v := v.(*RevokeRelayPairingRequest); i { case 0: return &v.state case 1: @@ -1960,7 +2922,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WebEncryptionKeyResponse); i { + switch v := v.(*RevokeRelayPairingResponse); i { case 0: return &v.state case 1: @@ -1972,7 +2934,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ErrorResponse); i { + switch v := v.(*RegisterRefreshRequest); i { case 0: return &v.state case 1: @@ -1984,7 +2946,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ECDSAKeys); i { + switch v := v.(*RegisterRefreshResponse); i { case 0: return &v.state case 1: @@ -1996,7 +2958,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CurrentDeviceData); i { + switch v := v.(*RegisterPhoneRelayResponse); i { case 0: return &v.state case 1: @@ -2008,7 +2970,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*KeyData); i { + switch v := v.(*CoordinateMessage); i { case 0: return &v.state case 1: @@ -2020,7 +2982,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WebAuthKey); i { + switch v := v.(*RefreshPhoneRelayResponse); i { case 0: return &v.state case 1: @@ -2032,7 +2994,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*URLData); i { + switch v := v.(*WebEncryptionKeyResponse); i { case 0: return &v.state case 1: @@ -2044,7 +3006,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*TokenData); i { + switch v := v.(*ErrorResponse); i { case 0: return &v.state case 1: @@ -2056,7 +3018,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PairedData); i { + switch v := v.(*ECDSAKeys); i { case 0: return &v.state case 1: @@ -2068,7 +3030,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RevokePairData); i { + switch v := v.(*CurrentDeviceData); i { case 0: return &v.state case 1: @@ -2080,7 +3042,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterRefreshRequest_NestedEmptyArr); i { + switch v := v.(*KeyData); i { case 0: return &v.state case 1: @@ -2092,7 +3054,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterRefreshResponse_AuthKeyData); i { + switch v := v.(*WebAuthKey); i { case 0: return &v.state case 1: @@ -2104,7 +3066,7 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RegisterPhoneRelayResponse_AuthKeyData); i { + switch v := v.(*URLData); i { case 0: return &v.state case 1: @@ -2116,6 +3078,186 @@ func file_authentication_proto_init() { } } file_authentication_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TokenData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PairedData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RevokePairData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignInGaiaRequest_Inner); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignInGaiaRequest_Inner_DeviceID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignInGaiaRequest_Inner_Data); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignInGaiaResponse_Header); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignInGaiaResponse_DeviceData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SignInGaiaResponse_DeviceData_DeviceWrapper); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RPCGaiaData_UnknownContainer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RPCGaiaData_UnknownContainer_Item2); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RPCGaiaData_UnknownContainer_Item4); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RPCGaiaData_UnknownContainer_Item2_Item1); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RPCGaiaData_UnknownContainer_Item4_Item8); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterRefreshRequest_NestedEmptyArr); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authentication_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ErrorResponse_ErrorClass); i { case 0: return &v.state @@ -2128,18 +3270,17 @@ func file_authentication_proto_init() { } } } - file_authentication_proto_msgTypes[3].OneofWrappers = []interface{}{ + file_authentication_proto_msgTypes[9].OneofWrappers = []interface{}{ (*AuthenticationContainer_KeyData)(nil), (*AuthenticationContainer_DeviceData)(nil), } - file_authentication_proto_msgTypes[4].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_authentication_proto_rawDesc, NumEnums: 2, - NumMessages: 26, + NumMessages: 41, NumExtensions: 0, NumServices: 0, }, diff --git a/libgm/gmproto/authentication.pb.raw b/libgm/gmproto/authentication.pb.raw index b486d88..4982063 100644 Binary files a/libgm/gmproto/authentication.pb.raw and b/libgm/gmproto/authentication.pb.raw differ diff --git a/libgm/gmproto/authentication.proto b/libgm/gmproto/authentication.proto index 5f8b91d..09a9c76 100644 --- a/libgm/gmproto/authentication.proto +++ b/libgm/gmproto/authentication.proto @@ -4,6 +4,7 @@ package authentication; option go_package = "../gmproto"; import "util.proto"; +import "pblite.proto"; enum BrowserType { UNKNOWN_BROWSER_TYPE = 0; @@ -44,6 +45,95 @@ message ConfigVersion { int32 V2 = 9; } +message SignInGaiaRequest { + message Inner { + message DeviceID { + int32 unknownInt1 = 1; // 3 + string deviceID = 2; // messages-web-{uuid without dashes} + } + message Data { + bytes someData = 3; // maybe an encryption key? + } + DeviceID deviceID = 1; + Data someData = 36 [(pblite.pblite_binary) = true]; + } + AuthMessage authMessage = 1; + Inner inner = 2; + int32 unknownInt3 = 3; + string network = 4; +} + +message SignInGaiaResponse { + message Header { + uint64 unknownInt2 = 2; + int64 unknownTimestamp = 4; + } + message DeviceData { + message DeviceWrapper { + Device device = 1; + } + DeviceWrapper deviceWrapper = 1; + repeated RPCGaiaData.UnknownContainer.Item2.Item1 unknownItems2 = 2; + repeated RPCGaiaData.UnknownContainer.Item4 unknownItems3 = 3; + // index 4 is some unknown field with no real data + } + Header header = 1; + string maybeBrowserUUID = 2 [(pblite.pblite_binary) = true]; + DeviceData deviceData = 3; + TokenData tokenData = 4; +} + +message GaiaPairingRequestContainer { + string pairingAttemptID = 1; + BrowserDetails browserDetails = 2; + int64 startTimestamp = 3; + bytes data = 4; +} + +message GaiaPairingResponseContainer { + int32 finishErrorType = 1; + int32 finishErrorCode = 2; + int32 unknownInt3 = 3; // For init, 1 + string sessionUUID = 4; + bytes data = 5; +} + +message RevokeGaiaPairingRequest { + string pairingAttemptID = 1; +} + +message RPCGaiaData { + message UnknownContainer { + message Item2 { + message Item1 { + string destOrSourceUUID = 1 [(pblite.pblite_binary) = true]; + int32 unknownInt4 = 4; // 1 for destination device, 6 for local device? + string languageCode = 5; + uint64 unknownBigInt7 = 7; + } + repeated Item1 item1 = 1; + } + message Item4 { + message Item8 { + int32 unknownInt1 = 1; // present for destination device? + int32 unknownTimestamp = 2; // present for destination device? + bytes unknownBytes = 3; // present for local device? + } + string destOrSourceUUID = 1 [(pblite.pblite_binary) = true]; + int32 unknownInt3 = 3; // 1 for destination device, 6 for local device? + int32 unknownInt4 = 4; // always 6? + int64 unknownTimestampMicroseconds = 7; // maybe device creation ts? + Item8 item8 = 8 [(pblite.pblite_binary) = true]; + } + Item2 item2 = 2; + int64 unknownTimestampMicroseconds = 3; // pairing timestamp? + repeated Item4 item4 = 4; + } + + int32 command = 1; // 9 + UnknownContainer maybeServerData = 108; +} + message AuthenticationContainer { AuthMessage authMessage = 1; BrowserDetails browserDetails = 3; @@ -56,8 +146,8 @@ message AuthenticationContainer { message AuthMessage { string requestID = 1; - optional string network = 3; - optional bytes tachyonAuthToken = 6; + string network = 3; + bytes tachyonAuthToken = 6; ConfigVersion configVersion = 7; } @@ -84,25 +174,15 @@ message RegisterRefreshRequest { } message RegisterRefreshResponse { - message AuthKeyData { - bytes tachyonAuthToken = 1; - string validFor = 2; - } - - AuthKeyData tokenData = 2; + TokenData tokenData = 2; } message RegisterPhoneRelayResponse { - message AuthKeyData { - bytes tachyonAuthToken = 1; - int64 validFor = 2; - } - CoordinateMessage coordinates = 1; Device browser = 2; bytes pairingKey = 3; int64 validFor = 4; - AuthKeyData authKeyData = 5; + TokenData authKeyData = 5; string responseID = 6; } diff --git a/libgm/gmproto/config-extra.go b/libgm/gmproto/config-extra.go new file mode 100644 index 0000000..cb9e2b0 --- /dev/null +++ b/libgm/gmproto/config-extra.go @@ -0,0 +1,43 @@ +package gmproto + +import ( + "strconv" +) + +func (c *Config) ParsedClientVersion() (*ConfigVersion, error) { + version := c.ClientVersion + + v1 := version[0:4] + v2 := version[4:6] + v3 := version[6:8] + + if v2[0] == 48 { + v2 = string(v2[1]) + } + if v3[0] == 48 { + v3 = string(v3[1]) + } + + first, e := strconv.Atoi(v1) + if e != nil { + return nil, e + } + + second, e1 := strconv.Atoi(v2) + if e1 != nil { + return nil, e1 + } + + third, e2 := strconv.Atoi(v3) + if e2 != nil { + return nil, e2 + } + + return &ConfigVersion{ + Year: int32(first), + Month: int32(second), + Day: int32(third), + V1: 4, + V2: 6, + }, nil +} diff --git a/libgm/gmproto/config.pb.go b/libgm/gmproto/config.pb.go new file mode 100644 index 0000000..ad1af37 --- /dev/null +++ b/libgm/gmproto/config.pb.go @@ -0,0 +1,587 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v3.21.12 +// source: config.proto + +package gmproto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +import _ "embed" + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Config struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClientVersion string `protobuf:"bytes,1,opt,name=clientVersion,proto3" json:"clientVersion,omitempty"` + ServerVersion string `protobuf:"bytes,2,opt,name=serverVersion,proto3" json:"serverVersion,omitempty"` + IntFlags []*Config_Flag `protobuf:"bytes,3,rep,name=intFlags,proto3" json:"intFlags,omitempty"` + MoreFlags *Config_MoreFlags `protobuf:"bytes,4,opt,name=moreFlags,proto3" json:"moreFlags,omitempty"` + DeviceInfo *Config_DeviceInfo `protobuf:"bytes,5,opt,name=deviceInfo,proto3" json:"deviceInfo,omitempty"` + // item 6 seems like a list of device infos without device ID? + CountryCode string `protobuf:"bytes,7,opt,name=countryCode,proto3" json:"countryCode,omitempty"` + UnknownInts []uint32 `protobuf:"varint,8,rep,packed,name=unknownInts,proto3" json:"unknownInts,omitempty"` + GeneratedAtMS int64 `protobuf:"varint,9,opt,name=generatedAtMS,proto3" json:"generatedAtMS,omitempty"` +} + +func (x *Config) Reset() { + *x = Config{} + if protoimpl.UnsafeEnabled { + mi := &file_config_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Config) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Config) ProtoMessage() {} + +func (x *Config) ProtoReflect() protoreflect.Message { + mi := &file_config_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Config.ProtoReflect.Descriptor instead. +func (*Config) Descriptor() ([]byte, []int) { + return file_config_proto_rawDescGZIP(), []int{0} +} + +func (x *Config) GetClientVersion() string { + if x != nil { + return x.ClientVersion + } + return "" +} + +func (x *Config) GetServerVersion() string { + if x != nil { + return x.ServerVersion + } + return "" +} + +func (x *Config) GetIntFlags() []*Config_Flag { + if x != nil { + return x.IntFlags + } + return nil +} + +func (x *Config) GetMoreFlags() *Config_MoreFlags { + if x != nil { + return x.MoreFlags + } + return nil +} + +func (x *Config) GetDeviceInfo() *Config_DeviceInfo { + if x != nil { + return x.DeviceInfo + } + return nil +} + +func (x *Config) GetCountryCode() string { + if x != nil { + return x.CountryCode + } + return "" +} + +func (x *Config) GetUnknownInts() []uint32 { + if x != nil { + return x.UnknownInts + } + return nil +} + +func (x *Config) GetGeneratedAtMS() int64 { + if x != nil { + return x.GeneratedAtMS + } + return 0 +} + +type Config_Flag struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value int32 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` + UnknownField4 *string `protobuf:"bytes,4,opt,name=unknownField4,proto3,oneof" json:"unknownField4,omitempty"` + UnknownField5 *string `protobuf:"bytes,5,opt,name=unknownField5,proto3,oneof" json:"unknownField5,omitempty"` +} + +func (x *Config_Flag) Reset() { + *x = Config_Flag{} + if protoimpl.UnsafeEnabled { + mi := &file_config_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Config_Flag) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Config_Flag) ProtoMessage() {} + +func (x *Config_Flag) ProtoReflect() protoreflect.Message { + mi := &file_config_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Config_Flag.ProtoReflect.Descriptor instead. +func (*Config_Flag) Descriptor() ([]byte, []int) { + return file_config_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *Config_Flag) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *Config_Flag) GetValue() int32 { + if x != nil { + return x.Value + } + return 0 +} + +func (x *Config_Flag) GetUnknownField4() string { + if x != nil && x.UnknownField4 != nil { + return *x.UnknownField4 + } + return "" +} + +func (x *Config_Flag) GetUnknownField5() string { + if x != nil && x.UnknownField5 != nil { + return *x.UnknownField5 + } + return "" +} + +type Config_WrappedFlag struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value *Config_WrappedFlag_Value `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Config_WrappedFlag) Reset() { + *x = Config_WrappedFlag{} + if protoimpl.UnsafeEnabled { + mi := &file_config_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Config_WrappedFlag) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Config_WrappedFlag) ProtoMessage() {} + +func (x *Config_WrappedFlag) ProtoReflect() protoreflect.Message { + mi := &file_config_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Config_WrappedFlag.ProtoReflect.Descriptor instead. +func (*Config_WrappedFlag) Descriptor() ([]byte, []int) { + return file_config_proto_rawDescGZIP(), []int{0, 1} +} + +func (x *Config_WrappedFlag) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *Config_WrappedFlag) GetValue() *Config_WrappedFlag_Value { + if x != nil { + return x.Value + } + return nil +} + +type Config_MoreFlags struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + WrappedFlags []*Config_WrappedFlag `protobuf:"bytes,1,rep,name=wrappedFlags,proto3" json:"wrappedFlags,omitempty"` +} + +func (x *Config_MoreFlags) Reset() { + *x = Config_MoreFlags{} + if protoimpl.UnsafeEnabled { + mi := &file_config_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Config_MoreFlags) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Config_MoreFlags) ProtoMessage() {} + +func (x *Config_MoreFlags) ProtoReflect() protoreflect.Message { + mi := &file_config_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Config_MoreFlags.ProtoReflect.Descriptor instead. +func (*Config_MoreFlags) Descriptor() ([]byte, []int) { + return file_config_proto_rawDescGZIP(), []int{0, 2} +} + +func (x *Config_MoreFlags) GetWrappedFlags() []*Config_WrappedFlag { + if x != nil { + return x.WrappedFlags + } + return nil +} + +type Config_DeviceInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` + Zero string `protobuf:"bytes,3,opt,name=zero,proto3" json:"zero,omitempty"` + DeviceID string `protobuf:"bytes,4,opt,name=deviceID,proto3" json:"deviceID,omitempty"` +} + +func (x *Config_DeviceInfo) Reset() { + *x = Config_DeviceInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_config_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Config_DeviceInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Config_DeviceInfo) ProtoMessage() {} + +func (x *Config_DeviceInfo) ProtoReflect() protoreflect.Message { + mi := &file_config_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Config_DeviceInfo.ProtoReflect.Descriptor instead. +func (*Config_DeviceInfo) Descriptor() ([]byte, []int) { + return file_config_proto_rawDescGZIP(), []int{0, 3} +} + +func (x *Config_DeviceInfo) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +func (x *Config_DeviceInfo) GetZero() string { + if x != nil { + return x.Zero + } + return "" +} + +func (x *Config_DeviceInfo) GetDeviceID() string { + if x != nil { + return x.DeviceID + } + return "" +} + +type Config_WrappedFlag_Value struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Value: + // + // *Config_WrappedFlag_Value_IntVal + // *Config_WrappedFlag_Value_StrVal + Value isConfig_WrappedFlag_Value_Value `protobuf_oneof:"value"` +} + +func (x *Config_WrappedFlag_Value) Reset() { + *x = Config_WrappedFlag_Value{} + if protoimpl.UnsafeEnabled { + mi := &file_config_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Config_WrappedFlag_Value) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Config_WrappedFlag_Value) ProtoMessage() {} + +func (x *Config_WrappedFlag_Value) ProtoReflect() protoreflect.Message { + mi := &file_config_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Config_WrappedFlag_Value.ProtoReflect.Descriptor instead. +func (*Config_WrappedFlag_Value) Descriptor() ([]byte, []int) { + return file_config_proto_rawDescGZIP(), []int{0, 1, 0} +} + +func (m *Config_WrappedFlag_Value) GetValue() isConfig_WrappedFlag_Value_Value { + if m != nil { + return m.Value + } + return nil +} + +func (x *Config_WrappedFlag_Value) GetIntVal() int32 { + if x, ok := x.GetValue().(*Config_WrappedFlag_Value_IntVal); ok { + return x.IntVal + } + return 0 +} + +func (x *Config_WrappedFlag_Value) GetStrVal() string { + if x, ok := x.GetValue().(*Config_WrappedFlag_Value_StrVal); ok { + return x.StrVal + } + return "" +} + +type isConfig_WrappedFlag_Value_Value interface { + isConfig_WrappedFlag_Value_Value() +} + +type Config_WrappedFlag_Value_IntVal struct { + IntVal int32 `protobuf:"varint,2,opt,name=intVal,proto3,oneof"` +} + +type Config_WrappedFlag_Value_StrVal struct { + StrVal string `protobuf:"bytes,3,opt,name=strVal,proto3,oneof"` +} + +func (*Config_WrappedFlag_Value_IntVal) isConfig_WrappedFlag_Value_Value() {} + +func (*Config_WrappedFlag_Value_StrVal) isConfig_WrappedFlag_Value_Value() {} + +var File_config_proto protoreflect.FileDescriptor + +//go:embed config.pb.raw +var file_config_proto_rawDesc []byte + +var ( + file_config_proto_rawDescOnce sync.Once + file_config_proto_rawDescData = file_config_proto_rawDesc +) + +func file_config_proto_rawDescGZIP() []byte { + file_config_proto_rawDescOnce.Do(func() { + file_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_config_proto_rawDescData) + }) + return file_config_proto_rawDescData +} + +var file_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_config_proto_goTypes = []interface{}{ + (*Config)(nil), // 0: config.Config + (*Config_Flag)(nil), // 1: config.Config.Flag + (*Config_WrappedFlag)(nil), // 2: config.Config.WrappedFlag + (*Config_MoreFlags)(nil), // 3: config.Config.MoreFlags + (*Config_DeviceInfo)(nil), // 4: config.Config.DeviceInfo + (*Config_WrappedFlag_Value)(nil), // 5: config.Config.WrappedFlag.Value +} +var file_config_proto_depIdxs = []int32{ + 1, // 0: config.Config.intFlags:type_name -> config.Config.Flag + 3, // 1: config.Config.moreFlags:type_name -> config.Config.MoreFlags + 4, // 2: config.Config.deviceInfo:type_name -> config.Config.DeviceInfo + 5, // 3: config.Config.WrappedFlag.value:type_name -> config.Config.WrappedFlag.Value + 2, // 4: config.Config.MoreFlags.wrappedFlags:type_name -> config.Config.WrappedFlag + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name +} + +func init() { file_config_proto_init() } +func file_config_proto_init() { + if File_config_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Config); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Config_Flag); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Config_WrappedFlag); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Config_MoreFlags); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Config_DeviceInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Config_WrappedFlag_Value); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_config_proto_msgTypes[1].OneofWrappers = []interface{}{} + file_config_proto_msgTypes[5].OneofWrappers = []interface{}{ + (*Config_WrappedFlag_Value_IntVal)(nil), + (*Config_WrappedFlag_Value_StrVal)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_config_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_config_proto_goTypes, + DependencyIndexes: file_config_proto_depIdxs, + MessageInfos: file_config_proto_msgTypes, + }.Build() + File_config_proto = out.File + file_config_proto_rawDesc = nil + file_config_proto_goTypes = nil + file_config_proto_depIdxs = nil +} diff --git a/libgm/gmproto/config.pb.raw b/libgm/gmproto/config.pb.raw new file mode 100644 index 0000000..24cd09d Binary files /dev/null and b/libgm/gmproto/config.pb.raw differ diff --git a/libgm/gmproto/config.proto b/libgm/gmproto/config.proto new file mode 100644 index 0000000..b78e355 --- /dev/null +++ b/libgm/gmproto/config.proto @@ -0,0 +1,40 @@ +syntax = "proto3"; +package config; + +option go_package = "../gmproto"; + +message Config { + message Flag { + string key = 1; + int32 value = 2; + optional string unknownField4 = 4; + optional string unknownField5 = 5; + } + message WrappedFlag { + message Value { + oneof value { + int32 intVal = 2; + string strVal = 3; + } + } + string key = 1; + Value value = 2; + } + message MoreFlags { + repeated WrappedFlag wrappedFlags = 1; + } + message DeviceInfo { + string email = 2; + string zero = 3; + string deviceID = 4; + } + string clientVersion = 1; + string serverVersion = 2; + repeated Flag intFlags = 3; + MoreFlags moreFlags = 4; + DeviceInfo deviceInfo = 5; + // item 6 seems like a list of device infos without device ID? + string countryCode = 7; + repeated uint32 unknownInts = 8; + int64 generatedAtMS = 9; +} diff --git a/libgm/gmproto/pblite.pb.go b/libgm/gmproto/pblite.pb.go new file mode 100644 index 0000000..7d49b56 --- /dev/null +++ b/libgm/gmproto/pblite.pb.go @@ -0,0 +1,82 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v3.21.12 +// source: pblite.proto + +package gmproto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + descriptorpb "google.golang.org/protobuf/types/descriptorpb" + reflect "reflect" +) + +import _ "embed" + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +var file_pblite_proto_extTypes = []protoimpl.ExtensionInfo{ + { + ExtendedType: (*descriptorpb.FieldOptions)(nil), + ExtensionType: (*bool)(nil), + Field: 50000, + Name: "pblite.pblite_binary", + Tag: "varint,50000,opt,name=pblite_binary", + Filename: "pblite.proto", + }, +} + +// Extension fields to descriptorpb.FieldOptions. +var ( + // optional bool pblite_binary = 50000; + E_PbliteBinary = &file_pblite_proto_extTypes[0] +) + +var File_pblite_proto protoreflect.FileDescriptor + +//go:embed pblite.pb.raw +var file_pblite_proto_rawDesc []byte + +var file_pblite_proto_goTypes = []interface{}{ + (*descriptorpb.FieldOptions)(nil), // 0: google.protobuf.FieldOptions +} +var file_pblite_proto_depIdxs = []int32{ + 0, // 0: pblite.pblite_binary:extendee -> google.protobuf.FieldOptions + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 0, // [0:1] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_pblite_proto_init() } +func file_pblite_proto_init() { + if File_pblite_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_pblite_proto_rawDesc, + NumEnums: 0, + NumMessages: 0, + NumExtensions: 1, + NumServices: 0, + }, + GoTypes: file_pblite_proto_goTypes, + DependencyIndexes: file_pblite_proto_depIdxs, + ExtensionInfos: file_pblite_proto_extTypes, + }.Build() + File_pblite_proto = out.File + file_pblite_proto_rawDesc = nil + file_pblite_proto_goTypes = nil + file_pblite_proto_depIdxs = nil +} diff --git a/libgm/gmproto/pblite.pb.raw b/libgm/gmproto/pblite.pb.raw new file mode 100644 index 0000000..6d091a9 --- /dev/null +++ b/libgm/gmproto/pblite.pb.raw @@ -0,0 +1,4 @@ + + pblite.protopblite google/protobuf/descriptor.proto:G + pblite_binary.google.protobuf.FieldOptionsะ† (R pbliteBinaryˆB Z +../gmprotobproto3 \ No newline at end of file diff --git a/libgm/gmproto/pblite.proto b/libgm/gmproto/pblite.proto new file mode 100644 index 0000000..1e6e2fc --- /dev/null +++ b/libgm/gmproto/pblite.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +package pblite; + +option go_package = "../gmproto"; + +import "google/protobuf/descriptor.proto"; + +extend google.protobuf.FieldOptions { + optional bool pblite_binary = 50000; +} diff --git a/libgm/gmproto/rpc.pb.go b/libgm/gmproto/rpc.pb.go index 1c0d90f..af17c3e 100644 --- a/libgm/gmproto/rpc.pb.go +++ b/libgm/gmproto/rpc.pb.go @@ -28,6 +28,7 @@ const ( BugleRoute_Unknown BugleRoute = 0 BugleRoute_DataEvent BugleRoute = 19 BugleRoute_PairEvent BugleRoute = 14 + BugleRoute_GaiaEvent BugleRoute = 7 ) // Enum value maps for BugleRoute. @@ -36,11 +37,13 @@ var ( 0: "Unknown", 19: "DataEvent", 14: "PairEvent", + 7: "GaiaEvent", } BugleRoute_value = map[string]int32{ "Unknown": 0, "DataEvent": 19, "PairEvent": 14, + "GaiaEvent": 7, } ) @@ -119,6 +122,7 @@ const ( ActionType_CREATE_GAIA_PAIRING_CLIENT_INIT ActionType = 44 ActionType_CREATE_GAIA_PAIRING_CLIENT_FINISHED ActionType = 45 ActionType_UNPAIR_GAIA_PAIRING ActionType = 46 + ActionType_CANCEL_GAIA_PAIRING ActionType = 47 ) // Enum value maps for ActionType. @@ -169,6 +173,7 @@ var ( 44: "CREATE_GAIA_PAIRING_CLIENT_INIT", 45: "CREATE_GAIA_PAIRING_CLIENT_FINISHED", 46: "UNPAIR_GAIA_PAIRING", + 47: "CANCEL_GAIA_PAIRING", } ActionType_value = map[string]int32{ "UNSPECIFIED": 0, @@ -216,6 +221,7 @@ var ( "CREATE_GAIA_PAIRING_CLIENT_INIT": 44, "CREATE_GAIA_PAIRING_CLIENT_FINISHED": 45, "UNPAIR_GAIA_PAIRING": 46, + "CANCEL_GAIA_PAIRING": 47, } ) @@ -251,7 +257,9 @@ type MessageType int32 const ( MessageType_UNKNOWN_MESSAGE_TYPE MessageType = 0 MessageType_BUGLE_MESSAGE MessageType = 2 + MessageType_GAIA_1 MessageType = 3 MessageType_BUGLE_ANNOTATION MessageType = 16 + MessageType_GAIA_2 MessageType = 20 ) // Enum value maps for MessageType. @@ -259,12 +267,16 @@ var ( MessageType_name = map[int32]string{ 0: "UNKNOWN_MESSAGE_TYPE", 2: "BUGLE_MESSAGE", + 3: "GAIA_1", 16: "BUGLE_ANNOTATION", + 20: "GAIA_2", } MessageType_value = map[string]int32{ "UNKNOWN_MESSAGE_TYPE": 0, "BUGLE_MESSAGE": 2, + "GAIA_1": 3, "BUGLE_ANNOTATION": 16, + "GAIA_2": 20, } ) @@ -420,16 +432,18 @@ type IncomingRPCMessage struct { ResponseID string `protobuf:"bytes,1,opt,name=responseID,proto3" json:"responseID,omitempty"` BugleRoute BugleRoute `protobuf:"varint,2,opt,name=bugleRoute,proto3,enum=rpc.BugleRoute" json:"bugleRoute,omitempty"` - StartExecute string `protobuf:"bytes,3,opt,name=startExecute,proto3" json:"startExecute,omitempty"` + StartExecute uint64 `protobuf:"varint,3,opt,name=startExecute,proto3" json:"startExecute,omitempty"` MessageType MessageType `protobuf:"varint,5,opt,name=messageType,proto3,enum=rpc.MessageType" json:"messageType,omitempty"` - FinishExecute string `protobuf:"bytes,6,opt,name=finishExecute,proto3" json:"finishExecute,omitempty"` - MillisecondsTaken string `protobuf:"bytes,7,opt,name=millisecondsTaken,proto3" json:"millisecondsTaken,omitempty"` + FinishExecute uint64 `protobuf:"varint,6,opt,name=finishExecute,proto3" json:"finishExecute,omitempty"` + MicrosecondsTaken uint64 `protobuf:"varint,7,opt,name=microsecondsTaken,proto3" json:"microsecondsTaken,omitempty"` Mobile *Device `protobuf:"bytes,8,opt,name=mobile,proto3" json:"mobile,omitempty"` Browser *Device `protobuf:"bytes,9,opt,name=browser,proto3" json:"browser,omitempty"` // Either a RPCMessageData or a RPCPairData encoded as bytes MessageData []byte `protobuf:"bytes,12,opt,name=messageData,proto3" json:"messageData,omitempty"` SignatureID string `protobuf:"bytes,17,opt,name=signatureID,proto3" json:"signatureID,omitempty"` Timestamp string `protobuf:"bytes,21,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Completely unsure about this, but it seems to be present for weird intermediate responses + GdittoSource *IncomingRPCMessage_GDittoSource `protobuf:"bytes,23,opt,name=gdittoSource,proto3" json:"gdittoSource,omitempty"` } func (x *IncomingRPCMessage) Reset() { @@ -478,11 +492,11 @@ func (x *IncomingRPCMessage) GetBugleRoute() BugleRoute { return BugleRoute_Unknown } -func (x *IncomingRPCMessage) GetStartExecute() string { +func (x *IncomingRPCMessage) GetStartExecute() uint64 { if x != nil { return x.StartExecute } - return "" + return 0 } func (x *IncomingRPCMessage) GetMessageType() MessageType { @@ -492,18 +506,18 @@ func (x *IncomingRPCMessage) GetMessageType() MessageType { return MessageType_UNKNOWN_MESSAGE_TYPE } -func (x *IncomingRPCMessage) GetFinishExecute() string { +func (x *IncomingRPCMessage) GetFinishExecute() uint64 { if x != nil { return x.FinishExecute } - return "" + return 0 } -func (x *IncomingRPCMessage) GetMillisecondsTaken() string { +func (x *IncomingRPCMessage) GetMicrosecondsTaken() uint64 { if x != nil { - return x.MillisecondsTaken + return x.MicrosecondsTaken } - return "" + return 0 } func (x *IncomingRPCMessage) GetMobile() *Device { @@ -541,19 +555,27 @@ func (x *IncomingRPCMessage) GetTimestamp() string { return "" } +func (x *IncomingRPCMessage) GetGdittoSource() *IncomingRPCMessage_GDittoSource { + if x != nil { + return x.GdittoSource + } + return nil +} + type RPCMessageData struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - SessionID string `protobuf:"bytes,1,opt,name=sessionID,proto3" json:"sessionID,omitempty"` - Timestamp int64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - Action ActionType `protobuf:"varint,4,opt,name=action,proto3,enum=rpc.ActionType" json:"action,omitempty"` - Bool1 bool `protobuf:"varint,6,opt,name=bool1,proto3" json:"bool1,omitempty"` - Bool2 bool `protobuf:"varint,7,opt,name=bool2,proto3" json:"bool2,omitempty"` - EncryptedData []byte `protobuf:"bytes,8,opt,name=encryptedData,proto3" json:"encryptedData,omitempty"` - Bool3 bool `protobuf:"varint,9,opt,name=bool3,proto3" json:"bool3,omitempty"` - EncryptedData2 []byte `protobuf:"bytes,11,opt,name=encryptedData2,proto3" json:"encryptedData2,omitempty"` + SessionID string `protobuf:"bytes,1,opt,name=sessionID,proto3" json:"sessionID,omitempty"` + Timestamp int64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Action ActionType `protobuf:"varint,4,opt,name=action,proto3,enum=rpc.ActionType" json:"action,omitempty"` + UnencryptedData []byte `protobuf:"bytes,5,opt,name=unencryptedData,proto3" json:"unencryptedData,omitempty"` + Bool1 bool `protobuf:"varint,6,opt,name=bool1,proto3" json:"bool1,omitempty"` + Bool2 bool `protobuf:"varint,7,opt,name=bool2,proto3" json:"bool2,omitempty"` + EncryptedData []byte `protobuf:"bytes,8,opt,name=encryptedData,proto3" json:"encryptedData,omitempty"` + Bool3 bool `protobuf:"varint,9,opt,name=bool3,proto3" json:"bool3,omitempty"` + EncryptedData2 []byte `protobuf:"bytes,11,opt,name=encryptedData2,proto3" json:"encryptedData2,omitempty"` } func (x *RPCMessageData) Reset() { @@ -609,6 +631,13 @@ func (x *RPCMessageData) GetAction() ActionType { return ActionType_UNSPECIFIED } +func (x *RPCMessageData) GetUnencryptedData() []byte { + if x != nil { + return x.UnencryptedData + } + return nil +} + func (x *RPCMessageData) GetBool1() bool { if x != nil { return x.Bool1 @@ -649,11 +678,11 @@ type OutgoingRPCMessage struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Mobile *Device `protobuf:"bytes,1,opt,name=mobile,proto3" json:"mobile,omitempty"` - Data *OutgoingRPCMessage_Data `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` - Auth *OutgoingRPCMessage_Auth `protobuf:"bytes,3,opt,name=auth,proto3" json:"auth,omitempty"` - TTL int64 `protobuf:"varint,5,opt,name=TTL,proto3" json:"TTL,omitempty"` - EmptyArr *EmptyArr `protobuf:"bytes,9,opt,name=emptyArr,proto3" json:"emptyArr,omitempty"` + Mobile *Device `protobuf:"bytes,1,opt,name=mobile,proto3" json:"mobile,omitempty"` + Data *OutgoingRPCMessage_Data `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` + Auth *OutgoingRPCMessage_Auth `protobuf:"bytes,3,opt,name=auth,proto3" json:"auth,omitempty"` + TTL int64 `protobuf:"varint,5,opt,name=TTL,proto3" json:"TTL,omitempty"` + DestRegistrationIDs []string `protobuf:"bytes,9,rep,name=destRegistrationIDs,proto3" json:"destRegistrationIDs,omitempty"` } func (x *OutgoingRPCMessage) Reset() { @@ -716,9 +745,9 @@ func (x *OutgoingRPCMessage) GetTTL() int64 { return 0 } -func (x *OutgoingRPCMessage) GetEmptyArr() *EmptyArr { +func (x *OutgoingRPCMessage) GetDestRegistrationIDs() []string { if x != nil { - return x.EmptyArr + return x.DestRegistrationIDs } return nil } @@ -728,10 +757,11 @@ type OutgoingRPCData struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - RequestID string `protobuf:"bytes,1,opt,name=requestID,proto3" json:"requestID,omitempty"` - Action ActionType `protobuf:"varint,2,opt,name=action,proto3,enum=rpc.ActionType" json:"action,omitempty"` - EncryptedProtoData []byte `protobuf:"bytes,5,opt,name=encryptedProtoData,proto3" json:"encryptedProtoData,omitempty"` - SessionID string `protobuf:"bytes,6,opt,name=sessionID,proto3" json:"sessionID,omitempty"` + RequestID string `protobuf:"bytes,1,opt,name=requestID,proto3" json:"requestID,omitempty"` + Action ActionType `protobuf:"varint,2,opt,name=action,proto3,enum=rpc.ActionType" json:"action,omitempty"` + UnencryptedProtoData []byte `protobuf:"bytes,3,opt,name=unencryptedProtoData,proto3" json:"unencryptedProtoData,omitempty"` + EncryptedProtoData []byte `protobuf:"bytes,5,opt,name=encryptedProtoData,proto3" json:"encryptedProtoData,omitempty"` + SessionID string `protobuf:"bytes,6,opt,name=sessionID,proto3" json:"sessionID,omitempty"` } func (x *OutgoingRPCData) Reset() { @@ -780,6 +810,13 @@ func (x *OutgoingRPCData) GetAction() ActionType { return ActionType_UNSPECIFIED } +func (x *OutgoingRPCData) GetUnencryptedProtoData() []byte { + if x != nil { + return x.UnencryptedProtoData + } + return nil +} + func (x *OutgoingRPCData) GetEncryptedProtoData() []byte { if x != nil { return x.EncryptedProtoData @@ -850,6 +887,53 @@ func (x *OutgoingRPCResponse) GetTimestamp() string { return "" } +type IncomingRPCMessage_GDittoSource struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DeviceID int32 `protobuf:"varint,2,opt,name=deviceID,proto3" json:"deviceID,omitempty"` +} + +func (x *IncomingRPCMessage_GDittoSource) Reset() { + *x = IncomingRPCMessage_GDittoSource{} + if protoimpl.UnsafeEnabled { + mi := &file_rpc_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IncomingRPCMessage_GDittoSource) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IncomingRPCMessage_GDittoSource) ProtoMessage() {} + +func (x *IncomingRPCMessage_GDittoSource) ProtoReflect() protoreflect.Message { + mi := &file_rpc_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IncomingRPCMessage_GDittoSource.ProtoReflect.Descriptor instead. +func (*IncomingRPCMessage_GDittoSource) Descriptor() ([]byte, []int) { + return file_rpc_proto_rawDescGZIP(), []int{2, 0} +} + +func (x *IncomingRPCMessage_GDittoSource) GetDeviceID() int32 { + if x != nil { + return x.DeviceID + } + return 0 +} + type OutgoingRPCMessage_Auth struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -863,7 +947,7 @@ type OutgoingRPCMessage_Auth struct { func (x *OutgoingRPCMessage_Auth) Reset() { *x = OutgoingRPCMessage_Auth{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[7] + mi := &file_rpc_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -876,7 +960,7 @@ func (x *OutgoingRPCMessage_Auth) String() string { func (*OutgoingRPCMessage_Auth) ProtoMessage() {} func (x *OutgoingRPCMessage_Auth) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[7] + mi := &file_rpc_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -928,7 +1012,7 @@ type OutgoingRPCMessage_Data struct { func (x *OutgoingRPCMessage_Data) Reset() { *x = OutgoingRPCMessage_Data{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[8] + mi := &file_rpc_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -941,7 +1025,7 @@ func (x *OutgoingRPCMessage_Data) String() string { func (*OutgoingRPCMessage_Data) ProtoMessage() {} func (x *OutgoingRPCMessage_Data) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[8] + mi := &file_rpc_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -997,7 +1081,7 @@ type OutgoingRPCMessage_Data_Type struct { func (x *OutgoingRPCMessage_Data_Type) Reset() { *x = OutgoingRPCMessage_Data_Type{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[9] + mi := &file_rpc_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1010,7 +1094,7 @@ func (x *OutgoingRPCMessage_Data_Type) String() string { func (*OutgoingRPCMessage_Data_Type) ProtoMessage() {} func (x *OutgoingRPCMessage_Data_Type) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[9] + mi := &file_rpc_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1052,7 +1136,7 @@ type OutgoingRPCResponse_SomeIdentifier struct { func (x *OutgoingRPCResponse_SomeIdentifier) Reset() { *x = OutgoingRPCResponse_SomeIdentifier{} if protoimpl.UnsafeEnabled { - mi := &file_rpc_proto_msgTypes[10] + mi := &file_rpc_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1065,7 +1149,7 @@ func (x *OutgoingRPCResponse_SomeIdentifier) String() string { func (*OutgoingRPCResponse_SomeIdentifier) ProtoMessage() {} func (x *OutgoingRPCResponse_SomeIdentifier) ProtoReflect() protoreflect.Message { - mi := &file_rpc_proto_msgTypes[10] + mi := &file_rpc_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1106,7 +1190,7 @@ func file_rpc_proto_rawDescGZIP() []byte { } var file_rpc_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_rpc_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_rpc_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_rpc_proto_goTypes = []interface{}{ (BugleRoute)(0), // 0: rpc.BugleRoute (ActionType)(0), // 1: rpc.ActionType @@ -1118,34 +1202,35 @@ var file_rpc_proto_goTypes = []interface{}{ (*OutgoingRPCMessage)(nil), // 7: rpc.OutgoingRPCMessage (*OutgoingRPCData)(nil), // 8: rpc.OutgoingRPCData (*OutgoingRPCResponse)(nil), // 9: rpc.OutgoingRPCResponse - (*OutgoingRPCMessage_Auth)(nil), // 10: rpc.OutgoingRPCMessage.Auth - (*OutgoingRPCMessage_Data)(nil), // 11: rpc.OutgoingRPCMessage.Data - (*OutgoingRPCMessage_Data_Type)(nil), // 12: rpc.OutgoingRPCMessage.Data.Type - (*OutgoingRPCResponse_SomeIdentifier)(nil), // 13: rpc.OutgoingRPCResponse.SomeIdentifier - (*EmptyArr)(nil), // 14: util.EmptyArr - (*Device)(nil), // 15: authentication.Device - (*ConfigVersion)(nil), // 16: authentication.ConfigVersion + (*IncomingRPCMessage_GDittoSource)(nil), // 10: rpc.IncomingRPCMessage.GDittoSource + (*OutgoingRPCMessage_Auth)(nil), // 11: rpc.OutgoingRPCMessage.Auth + (*OutgoingRPCMessage_Data)(nil), // 12: rpc.OutgoingRPCMessage.Data + (*OutgoingRPCMessage_Data_Type)(nil), // 13: rpc.OutgoingRPCMessage.Data.Type + (*OutgoingRPCResponse_SomeIdentifier)(nil), // 14: rpc.OutgoingRPCResponse.SomeIdentifier + (*EmptyArr)(nil), // 15: util.EmptyArr + (*Device)(nil), // 16: authentication.Device + (*ConfigVersion)(nil), // 17: authentication.ConfigVersion } var file_rpc_proto_depIdxs = []int32{ 5, // 0: rpc.LongPollingPayload.data:type_name -> rpc.IncomingRPCMessage - 14, // 1: rpc.LongPollingPayload.heartbeat:type_name -> util.EmptyArr + 15, // 1: rpc.LongPollingPayload.heartbeat:type_name -> util.EmptyArr 3, // 2: rpc.LongPollingPayload.ack:type_name -> rpc.StartAckMessage - 14, // 3: rpc.LongPollingPayload.startRead:type_name -> util.EmptyArr + 15, // 3: rpc.LongPollingPayload.startRead:type_name -> util.EmptyArr 0, // 4: rpc.IncomingRPCMessage.bugleRoute:type_name -> rpc.BugleRoute 2, // 5: rpc.IncomingRPCMessage.messageType:type_name -> rpc.MessageType - 15, // 6: rpc.IncomingRPCMessage.mobile:type_name -> authentication.Device - 15, // 7: rpc.IncomingRPCMessage.browser:type_name -> authentication.Device - 1, // 8: rpc.RPCMessageData.action:type_name -> rpc.ActionType - 15, // 9: rpc.OutgoingRPCMessage.mobile:type_name -> authentication.Device - 11, // 10: rpc.OutgoingRPCMessage.data:type_name -> rpc.OutgoingRPCMessage.Data - 10, // 11: rpc.OutgoingRPCMessage.auth:type_name -> rpc.OutgoingRPCMessage.Auth - 14, // 12: rpc.OutgoingRPCMessage.emptyArr:type_name -> util.EmptyArr + 16, // 6: rpc.IncomingRPCMessage.mobile:type_name -> authentication.Device + 16, // 7: rpc.IncomingRPCMessage.browser:type_name -> authentication.Device + 10, // 8: rpc.IncomingRPCMessage.gdittoSource:type_name -> rpc.IncomingRPCMessage.GDittoSource + 1, // 9: rpc.RPCMessageData.action:type_name -> rpc.ActionType + 16, // 10: rpc.OutgoingRPCMessage.mobile:type_name -> authentication.Device + 12, // 11: rpc.OutgoingRPCMessage.data:type_name -> rpc.OutgoingRPCMessage.Data + 11, // 12: rpc.OutgoingRPCMessage.auth:type_name -> rpc.OutgoingRPCMessage.Auth 1, // 13: rpc.OutgoingRPCData.action:type_name -> rpc.ActionType - 13, // 14: rpc.OutgoingRPCResponse.someIdentifier:type_name -> rpc.OutgoingRPCResponse.SomeIdentifier - 16, // 15: rpc.OutgoingRPCMessage.Auth.configVersion:type_name -> authentication.ConfigVersion + 14, // 14: rpc.OutgoingRPCResponse.someIdentifier:type_name -> rpc.OutgoingRPCResponse.SomeIdentifier + 17, // 15: rpc.OutgoingRPCMessage.Auth.configVersion:type_name -> authentication.ConfigVersion 0, // 16: rpc.OutgoingRPCMessage.Data.bugleRoute:type_name -> rpc.BugleRoute - 12, // 17: rpc.OutgoingRPCMessage.Data.messageTypeData:type_name -> rpc.OutgoingRPCMessage.Data.Type - 14, // 18: rpc.OutgoingRPCMessage.Data.Type.emptyArr:type_name -> util.EmptyArr + 13, // 17: rpc.OutgoingRPCMessage.Data.messageTypeData:type_name -> rpc.OutgoingRPCMessage.Data.Type + 15, // 18: rpc.OutgoingRPCMessage.Data.Type.emptyArr:type_name -> util.EmptyArr 2, // 19: rpc.OutgoingRPCMessage.Data.Type.messageType:type_name -> rpc.MessageType 20, // [20:20] is the sub-list for method output_type 20, // [20:20] is the sub-list for method input_type @@ -1161,6 +1246,7 @@ func file_rpc_proto_init() { } file_authentication_proto_init() file_util_proto_init() + file_pblite_proto_init() if !protoimpl.UnsafeEnabled { file_rpc_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StartAckMessage); i { @@ -1247,7 +1333,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OutgoingRPCMessage_Auth); i { + switch v := v.(*IncomingRPCMessage_GDittoSource); i { case 0: return &v.state case 1: @@ -1259,7 +1345,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OutgoingRPCMessage_Data); i { + switch v := v.(*OutgoingRPCMessage_Auth); i { case 0: return &v.state case 1: @@ -1271,7 +1357,7 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OutgoingRPCMessage_Data_Type); i { + switch v := v.(*OutgoingRPCMessage_Data); i { case 0: return &v.state case 1: @@ -1283,6 +1369,18 @@ func file_rpc_proto_init() { } } file_rpc_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OutgoingRPCMessage_Data_Type); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_rpc_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*OutgoingRPCResponse_SomeIdentifier); i { case 0: return &v.state @@ -1304,7 +1402,7 @@ func file_rpc_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_rpc_proto_rawDesc, NumEnums: 3, - NumMessages: 11, + NumMessages: 12, NumExtensions: 0, NumServices: 0, }, diff --git a/libgm/gmproto/rpc.pb.raw b/libgm/gmproto/rpc.pb.raw index f4f889f..2a1ef3a 100644 Binary files a/libgm/gmproto/rpc.pb.raw and b/libgm/gmproto/rpc.pb.raw differ diff --git a/libgm/gmproto/rpc.proto b/libgm/gmproto/rpc.proto index ca35fb8..6abec8f 100644 --- a/libgm/gmproto/rpc.proto +++ b/libgm/gmproto/rpc.proto @@ -5,6 +5,7 @@ option go_package = "../gmproto"; import "authentication.proto"; import "util.proto"; +import "pblite.proto"; message StartAckMessage { optional int32 count = 1; @@ -20,11 +21,11 @@ message LongPollingPayload { message IncomingRPCMessage { string responseID = 1; BugleRoute bugleRoute = 2; - string startExecute = 3; + uint64 startExecute = 3; MessageType messageType = 5; - string finishExecute = 6; - string millisecondsTaken = 7; + uint64 finishExecute = 6; + uint64 microsecondsTaken = 7; authentication.Device mobile = 8; authentication.Device browser = 9; @@ -34,12 +35,20 @@ message IncomingRPCMessage { string signatureID = 17; string timestamp = 21; + + message GDittoSource { + int32 deviceID = 2; + } + + // Completely unsure about this, but it seems to be present for weird intermediate responses + GDittoSource gdittoSource = 23; } message RPCMessageData { string sessionID = 1; int64 timestamp = 3; ActionType action = 4; + bytes unencryptedData = 5; bool bool1 = 6; bool bool2 = 7; bytes encryptedData = 8; @@ -76,12 +85,13 @@ message OutgoingRPCMessage { int64 TTL = 5; - util.EmptyArr emptyArr = 9; + repeated string destRegistrationIDs = 9 [(pblite.pblite_binary) = true]; } message OutgoingRPCData { string requestID = 1; ActionType action = 2; + bytes unencryptedProtoData = 3; bytes encryptedProtoData = 5; string sessionID = 6; } @@ -101,6 +111,7 @@ enum BugleRoute { Unknown = 0; DataEvent = 19; PairEvent = 14; + GaiaEvent = 7; } enum ActionType { @@ -149,10 +160,13 @@ enum ActionType { CREATE_GAIA_PAIRING_CLIENT_INIT = 44; CREATE_GAIA_PAIRING_CLIENT_FINISHED = 45; UNPAIR_GAIA_PAIRING = 46; + CANCEL_GAIA_PAIRING = 47; } enum MessageType { UNKNOWN_MESSAGE_TYPE = 0; BUGLE_MESSAGE = 2; + GAIA_1 = 3; BUGLE_ANNOTATION = 16; + GAIA_2 = 20; } diff --git a/libgm/gmproto/ukey.pb.go b/libgm/gmproto/ukey.pb.go new file mode 100644 index 0000000..5f07c62 --- /dev/null +++ b/libgm/gmproto/ukey.pb.go @@ -0,0 +1,1091 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v3.21.12 +// source: ukey.proto + +package gmproto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +import _ "embed" + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Ukey2HandshakeCipher int32 + +const ( + Ukey2HandshakeCipher_RESERVED Ukey2HandshakeCipher = 0 + Ukey2HandshakeCipher_P256_SHA512 Ukey2HandshakeCipher = 100 // NIST P-256 used for ECDH, SHA512 used for commitment + Ukey2HandshakeCipher_CURVE25519_SHA512 Ukey2HandshakeCipher = 200 // Curve 25519 used for ECDH, SHA512 used for commitment +) + +// Enum value maps for Ukey2HandshakeCipher. +var ( + Ukey2HandshakeCipher_name = map[int32]string{ + 0: "RESERVED", + 100: "P256_SHA512", + 200: "CURVE25519_SHA512", + } + Ukey2HandshakeCipher_value = map[string]int32{ + "RESERVED": 0, + "P256_SHA512": 100, + "CURVE25519_SHA512": 200, + } +) + +func (x Ukey2HandshakeCipher) Enum() *Ukey2HandshakeCipher { + p := new(Ukey2HandshakeCipher) + *p = x + return p +} + +func (x Ukey2HandshakeCipher) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Ukey2HandshakeCipher) Descriptor() protoreflect.EnumDescriptor { + return file_ukey_proto_enumTypes[0].Descriptor() +} + +func (Ukey2HandshakeCipher) Type() protoreflect.EnumType { + return &file_ukey_proto_enumTypes[0] +} + +func (x Ukey2HandshakeCipher) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Ukey2HandshakeCipher.Descriptor instead. +func (Ukey2HandshakeCipher) EnumDescriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{0} +} + +// A list of supported public key types +type PublicKeyType int32 + +const ( + PublicKeyType_UNKNOWN_PUBLIC_KEY_TYPE PublicKeyType = 0 + PublicKeyType_EC_P256 PublicKeyType = 1 + PublicKeyType_RSA2048 PublicKeyType = 2 + // 2048-bit MODP group 14, from RFC 3526 + PublicKeyType_DH2048_MODP PublicKeyType = 3 +) + +// Enum value maps for PublicKeyType. +var ( + PublicKeyType_name = map[int32]string{ + 0: "UNKNOWN_PUBLIC_KEY_TYPE", + 1: "EC_P256", + 2: "RSA2048", + 3: "DH2048_MODP", + } + PublicKeyType_value = map[string]int32{ + "UNKNOWN_PUBLIC_KEY_TYPE": 0, + "EC_P256": 1, + "RSA2048": 2, + "DH2048_MODP": 3, + } +) + +func (x PublicKeyType) Enum() *PublicKeyType { + p := new(PublicKeyType) + *p = x + return p +} + +func (x PublicKeyType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PublicKeyType) Descriptor() protoreflect.EnumDescriptor { + return file_ukey_proto_enumTypes[1].Descriptor() +} + +func (PublicKeyType) Type() protoreflect.EnumType { + return &file_ukey_proto_enumTypes[1] +} + +func (x PublicKeyType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PublicKeyType.Descriptor instead. +func (PublicKeyType) EnumDescriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{1} +} + +type Ukey2Message_Type int32 + +const ( + Ukey2Message_UNKNOWN_DO_NOT_USE Ukey2Message_Type = 0 + Ukey2Message_ALERT Ukey2Message_Type = 1 + Ukey2Message_CLIENT_INIT Ukey2Message_Type = 2 + Ukey2Message_SERVER_INIT Ukey2Message_Type = 3 + Ukey2Message_CLIENT_FINISH Ukey2Message_Type = 4 +) + +// Enum value maps for Ukey2Message_Type. +var ( + Ukey2Message_Type_name = map[int32]string{ + 0: "UNKNOWN_DO_NOT_USE", + 1: "ALERT", + 2: "CLIENT_INIT", + 3: "SERVER_INIT", + 4: "CLIENT_FINISH", + } + Ukey2Message_Type_value = map[string]int32{ + "UNKNOWN_DO_NOT_USE": 0, + "ALERT": 1, + "CLIENT_INIT": 2, + "SERVER_INIT": 3, + "CLIENT_FINISH": 4, + } +) + +func (x Ukey2Message_Type) Enum() *Ukey2Message_Type { + p := new(Ukey2Message_Type) + *p = x + return p +} + +func (x Ukey2Message_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Ukey2Message_Type) Descriptor() protoreflect.EnumDescriptor { + return file_ukey_proto_enumTypes[2].Descriptor() +} + +func (Ukey2Message_Type) Type() protoreflect.EnumType { + return &file_ukey_proto_enumTypes[2] +} + +func (x Ukey2Message_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Ukey2Message_Type.Descriptor instead. +func (Ukey2Message_Type) EnumDescriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{0, 0} +} + +type Ukey2Alert_AlertType int32 + +const ( + Ukey2Alert_UNKNOWN_ALERT_TYPE Ukey2Alert_AlertType = 0 + // Framing errors + Ukey2Alert_BAD_MESSAGE Ukey2Alert_AlertType = 1 // The message could not be deserialized + Ukey2Alert_BAD_MESSAGE_TYPE Ukey2Alert_AlertType = 2 // message_type has an undefined value + Ukey2Alert_INCORRECT_MESSAGE Ukey2Alert_AlertType = 3 // message_type received does not correspond to expected type at this stage of the protocol + Ukey2Alert_BAD_MESSAGE_DATA Ukey2Alert_AlertType = 4 // Could not deserialize message_data as per value in message_type + // ClientInit and ServerInit errors + Ukey2Alert_BAD_VERSION Ukey2Alert_AlertType = 100 // version is invalid; server cannot find suitable version to speak with client. + Ukey2Alert_BAD_RANDOM Ukey2Alert_AlertType = 101 // Random data is missing or of incorrect length + Ukey2Alert_BAD_HANDSHAKE_CIPHER Ukey2Alert_AlertType = 102 // No suitable handshake ciphers were found + Ukey2Alert_BAD_NEXT_PROTOCOL Ukey2Alert_AlertType = 103 // The next protocol is missing, unknown, or unsupported + Ukey2Alert_BAD_PUBLIC_KEY Ukey2Alert_AlertType = 104 // The public key could not be parsed + // Other errors + Ukey2Alert_INTERNAL_ERROR Ukey2Alert_AlertType = 200 // An internal error has occurred. error_message may contain additional details for logging and debugging. +) + +// Enum value maps for Ukey2Alert_AlertType. +var ( + Ukey2Alert_AlertType_name = map[int32]string{ + 0: "UNKNOWN_ALERT_TYPE", + 1: "BAD_MESSAGE", + 2: "BAD_MESSAGE_TYPE", + 3: "INCORRECT_MESSAGE", + 4: "BAD_MESSAGE_DATA", + 100: "BAD_VERSION", + 101: "BAD_RANDOM", + 102: "BAD_HANDSHAKE_CIPHER", + 103: "BAD_NEXT_PROTOCOL", + 104: "BAD_PUBLIC_KEY", + 200: "INTERNAL_ERROR", + } + Ukey2Alert_AlertType_value = map[string]int32{ + "UNKNOWN_ALERT_TYPE": 0, + "BAD_MESSAGE": 1, + "BAD_MESSAGE_TYPE": 2, + "INCORRECT_MESSAGE": 3, + "BAD_MESSAGE_DATA": 4, + "BAD_VERSION": 100, + "BAD_RANDOM": 101, + "BAD_HANDSHAKE_CIPHER": 102, + "BAD_NEXT_PROTOCOL": 103, + "BAD_PUBLIC_KEY": 104, + "INTERNAL_ERROR": 200, + } +) + +func (x Ukey2Alert_AlertType) Enum() *Ukey2Alert_AlertType { + p := new(Ukey2Alert_AlertType) + *p = x + return p +} + +func (x Ukey2Alert_AlertType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Ukey2Alert_AlertType) Descriptor() protoreflect.EnumDescriptor { + return file_ukey_proto_enumTypes[3].Descriptor() +} + +func (Ukey2Alert_AlertType) Type() protoreflect.EnumType { + return &file_ukey_proto_enumTypes[3] +} + +func (x Ukey2Alert_AlertType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Ukey2Alert_AlertType.Descriptor instead. +func (Ukey2Alert_AlertType) EnumDescriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{1, 0} +} + +type Ukey2Message struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MessageType Ukey2Message_Type `protobuf:"varint,1,opt,name=message_type,json=messageType,proto3,enum=ukey.Ukey2Message_Type" json:"message_type,omitempty"` // Identifies message type + MessageData []byte `protobuf:"bytes,2,opt,name=message_data,json=messageData,proto3" json:"message_data,omitempty"` // Actual message, to be parsed according to message_type +} + +func (x *Ukey2Message) Reset() { + *x = Ukey2Message{} + if protoimpl.UnsafeEnabled { + mi := &file_ukey_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ukey2Message) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ukey2Message) ProtoMessage() {} + +func (x *Ukey2Message) ProtoReflect() protoreflect.Message { + mi := &file_ukey_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Ukey2Message.ProtoReflect.Descriptor instead. +func (*Ukey2Message) Descriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{0} +} + +func (x *Ukey2Message) GetMessageType() Ukey2Message_Type { + if x != nil { + return x.MessageType + } + return Ukey2Message_UNKNOWN_DO_NOT_USE +} + +func (x *Ukey2Message) GetMessageData() []byte { + if x != nil { + return x.MessageData + } + return nil +} + +type Ukey2Alert struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type Ukey2Alert_AlertType `protobuf:"varint,1,opt,name=type,proto3,enum=ukey.Ukey2Alert_AlertType" json:"type,omitempty"` + ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` +} + +func (x *Ukey2Alert) Reset() { + *x = Ukey2Alert{} + if protoimpl.UnsafeEnabled { + mi := &file_ukey_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ukey2Alert) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ukey2Alert) ProtoMessage() {} + +func (x *Ukey2Alert) ProtoReflect() protoreflect.Message { + mi := &file_ukey_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Ukey2Alert.ProtoReflect.Descriptor instead. +func (*Ukey2Alert) Descriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{1} +} + +func (x *Ukey2Alert) GetType() Ukey2Alert_AlertType { + if x != nil { + return x.Type + } + return Ukey2Alert_UNKNOWN_ALERT_TYPE +} + +func (x *Ukey2Alert) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} + +type Ukey2ClientInit struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version int32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // highest supported version for rollback protection + Random []byte `protobuf:"bytes,2,opt,name=random,proto3" json:"random,omitempty"` // random bytes for replay/reuse protection + CipherCommitments []*Ukey2ClientInit_CipherCommitment `protobuf:"bytes,3,rep,name=cipher_commitments,json=cipherCommitments,proto3" json:"cipher_commitments,omitempty"` + // Next protocol that the client wants to speak. + NextProtocol string `protobuf:"bytes,4,opt,name=next_protocol,json=nextProtocol,proto3" json:"next_protocol,omitempty"` +} + +func (x *Ukey2ClientInit) Reset() { + *x = Ukey2ClientInit{} + if protoimpl.UnsafeEnabled { + mi := &file_ukey_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ukey2ClientInit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ukey2ClientInit) ProtoMessage() {} + +func (x *Ukey2ClientInit) ProtoReflect() protoreflect.Message { + mi := &file_ukey_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Ukey2ClientInit.ProtoReflect.Descriptor instead. +func (*Ukey2ClientInit) Descriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{2} +} + +func (x *Ukey2ClientInit) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *Ukey2ClientInit) GetRandom() []byte { + if x != nil { + return x.Random + } + return nil +} + +func (x *Ukey2ClientInit) GetCipherCommitments() []*Ukey2ClientInit_CipherCommitment { + if x != nil { + return x.CipherCommitments + } + return nil +} + +func (x *Ukey2ClientInit) GetNextProtocol() string { + if x != nil { + return x.NextProtocol + } + return "" +} + +type Ukey2ServerInit struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version int32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` // highest supported version for rollback protection + Random []byte `protobuf:"bytes,2,opt,name=random,proto3" json:"random,omitempty"` // random bytes for replay/reuse protection + // Selected Cipher and corresponding public key + HandshakeCipher Ukey2HandshakeCipher `protobuf:"varint,3,opt,name=handshake_cipher,json=handshakeCipher,proto3,enum=ukey.Ukey2HandshakeCipher" json:"handshake_cipher,omitempty"` + PublicKey *GenericPublicKey `protobuf:"bytes,4,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` +} + +func (x *Ukey2ServerInit) Reset() { + *x = Ukey2ServerInit{} + if protoimpl.UnsafeEnabled { + mi := &file_ukey_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ukey2ServerInit) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ukey2ServerInit) ProtoMessage() {} + +func (x *Ukey2ServerInit) ProtoReflect() protoreflect.Message { + mi := &file_ukey_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Ukey2ServerInit.ProtoReflect.Descriptor instead. +func (*Ukey2ServerInit) Descriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{3} +} + +func (x *Ukey2ServerInit) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + +func (x *Ukey2ServerInit) GetRandom() []byte { + if x != nil { + return x.Random + } + return nil +} + +func (x *Ukey2ServerInit) GetHandshakeCipher() Ukey2HandshakeCipher { + if x != nil { + return x.HandshakeCipher + } + return Ukey2HandshakeCipher_RESERVED +} + +func (x *Ukey2ServerInit) GetPublicKey() *GenericPublicKey { + if x != nil { + return x.PublicKey + } + return nil +} + +type Ukey2ClientFinished struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PublicKey *GenericPublicKey `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // public key matching selected handshake cipher +} + +func (x *Ukey2ClientFinished) Reset() { + *x = Ukey2ClientFinished{} + if protoimpl.UnsafeEnabled { + mi := &file_ukey_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ukey2ClientFinished) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ukey2ClientFinished) ProtoMessage() {} + +func (x *Ukey2ClientFinished) ProtoReflect() protoreflect.Message { + mi := &file_ukey_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Ukey2ClientFinished.ProtoReflect.Descriptor instead. +func (*Ukey2ClientFinished) Descriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{4} +} + +func (x *Ukey2ClientFinished) GetPublicKey() *GenericPublicKey { + if x != nil { + return x.PublicKey + } + return nil +} + +// A convenience proto for encoding NIST P-256 elliptic curve public keys +type EcP256PublicKey struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // x and y are encoded in big-endian two's complement (slightly wasteful) + // Client MUST verify (x,y) is a valid point on NIST P256 + X []byte `protobuf:"bytes,1,opt,name=x,proto3" json:"x,omitempty"` + Y []byte `protobuf:"bytes,2,opt,name=y,proto3" json:"y,omitempty"` +} + +func (x *EcP256PublicKey) Reset() { + *x = EcP256PublicKey{} + if protoimpl.UnsafeEnabled { + mi := &file_ukey_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EcP256PublicKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EcP256PublicKey) ProtoMessage() {} + +func (x *EcP256PublicKey) ProtoReflect() protoreflect.Message { + mi := &file_ukey_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EcP256PublicKey.ProtoReflect.Descriptor instead. +func (*EcP256PublicKey) Descriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{5} +} + +func (x *EcP256PublicKey) GetX() []byte { + if x != nil { + return x.X + } + return nil +} + +func (x *EcP256PublicKey) GetY() []byte { + if x != nil { + return x.Y + } + return nil +} + +// A convenience proto for encoding RSA public keys with small exponents +type SimpleRsaPublicKey struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Encoded in big-endian two's complement + N []byte `protobuf:"bytes,1,opt,name=n,proto3" json:"n,omitempty"` + E int32 `protobuf:"varint,2,opt,name=e,proto3" json:"e,omitempty"` +} + +func (x *SimpleRsaPublicKey) Reset() { + *x = SimpleRsaPublicKey{} + if protoimpl.UnsafeEnabled { + mi := &file_ukey_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SimpleRsaPublicKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SimpleRsaPublicKey) ProtoMessage() {} + +func (x *SimpleRsaPublicKey) ProtoReflect() protoreflect.Message { + mi := &file_ukey_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SimpleRsaPublicKey.ProtoReflect.Descriptor instead. +func (*SimpleRsaPublicKey) Descriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{6} +} + +func (x *SimpleRsaPublicKey) GetN() []byte { + if x != nil { + return x.N + } + return nil +} + +func (x *SimpleRsaPublicKey) GetE() int32 { + if x != nil { + return x.E + } + return 0 +} + +// A convenience proto for encoding Diffie-Hellman public keys, +// for use only when Elliptic Curve based key exchanges are not possible. +// (Note that the group parameters must be specified separately) +type DhPublicKey struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Big-endian two's complement encoded group element + Y []byte `protobuf:"bytes,1,opt,name=y,proto3" json:"y,omitempty"` +} + +func (x *DhPublicKey) Reset() { + *x = DhPublicKey{} + if protoimpl.UnsafeEnabled { + mi := &file_ukey_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DhPublicKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DhPublicKey) ProtoMessage() {} + +func (x *DhPublicKey) ProtoReflect() protoreflect.Message { + mi := &file_ukey_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DhPublicKey.ProtoReflect.Descriptor instead. +func (*DhPublicKey) Descriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{7} +} + +func (x *DhPublicKey) GetY() []byte { + if x != nil { + return x.Y + } + return nil +} + +type GenericPublicKey struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type PublicKeyType `protobuf:"varint,1,opt,name=type,proto3,enum=ukey.PublicKeyType" json:"type,omitempty"` + // Types that are assignable to PublicKey: + // + // *GenericPublicKey_EcP256PublicKey + // *GenericPublicKey_Rsa2048PublicKey + // *GenericPublicKey_Dh2048PublicKey + PublicKey isGenericPublicKey_PublicKey `protobuf_oneof:"public_key"` +} + +func (x *GenericPublicKey) Reset() { + *x = GenericPublicKey{} + if protoimpl.UnsafeEnabled { + mi := &file_ukey_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GenericPublicKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GenericPublicKey) ProtoMessage() {} + +func (x *GenericPublicKey) ProtoReflect() protoreflect.Message { + mi := &file_ukey_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GenericPublicKey.ProtoReflect.Descriptor instead. +func (*GenericPublicKey) Descriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{8} +} + +func (x *GenericPublicKey) GetType() PublicKeyType { + if x != nil { + return x.Type + } + return PublicKeyType_UNKNOWN_PUBLIC_KEY_TYPE +} + +func (m *GenericPublicKey) GetPublicKey() isGenericPublicKey_PublicKey { + if m != nil { + return m.PublicKey + } + return nil +} + +func (x *GenericPublicKey) GetEcP256PublicKey() *EcP256PublicKey { + if x, ok := x.GetPublicKey().(*GenericPublicKey_EcP256PublicKey); ok { + return x.EcP256PublicKey + } + return nil +} + +func (x *GenericPublicKey) GetRsa2048PublicKey() *SimpleRsaPublicKey { + if x, ok := x.GetPublicKey().(*GenericPublicKey_Rsa2048PublicKey); ok { + return x.Rsa2048PublicKey + } + return nil +} + +func (x *GenericPublicKey) GetDh2048PublicKey() *DhPublicKey { + if x, ok := x.GetPublicKey().(*GenericPublicKey_Dh2048PublicKey); ok { + return x.Dh2048PublicKey + } + return nil +} + +type isGenericPublicKey_PublicKey interface { + isGenericPublicKey_PublicKey() +} + +type GenericPublicKey_EcP256PublicKey struct { + EcP256PublicKey *EcP256PublicKey `protobuf:"bytes,2,opt,name=ec_p256_public_key,json=ecP256PublicKey,proto3,oneof"` +} + +type GenericPublicKey_Rsa2048PublicKey struct { + Rsa2048PublicKey *SimpleRsaPublicKey `protobuf:"bytes,3,opt,name=rsa2048_public_key,json=rsa2048PublicKey,proto3,oneof"` +} + +type GenericPublicKey_Dh2048PublicKey struct { + // Use only as a last resort + Dh2048PublicKey *DhPublicKey `protobuf:"bytes,4,opt,name=dh2048_public_key,json=dh2048PublicKey,proto3,oneof"` +} + +func (*GenericPublicKey_EcP256PublicKey) isGenericPublicKey_PublicKey() {} + +func (*GenericPublicKey_Rsa2048PublicKey) isGenericPublicKey_PublicKey() {} + +func (*GenericPublicKey_Dh2048PublicKey) isGenericPublicKey_PublicKey() {} + +// One commitment (hash of ClientFinished containing public key) per supported cipher +type Ukey2ClientInit_CipherCommitment struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + HandshakeCipher Ukey2HandshakeCipher `protobuf:"varint,1,opt,name=handshake_cipher,json=handshakeCipher,proto3,enum=ukey.Ukey2HandshakeCipher" json:"handshake_cipher,omitempty"` + Commitment []byte `protobuf:"bytes,2,opt,name=commitment,proto3" json:"commitment,omitempty"` +} + +func (x *Ukey2ClientInit_CipherCommitment) Reset() { + *x = Ukey2ClientInit_CipherCommitment{} + if protoimpl.UnsafeEnabled { + mi := &file_ukey_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ukey2ClientInit_CipherCommitment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ukey2ClientInit_CipherCommitment) ProtoMessage() {} + +func (x *Ukey2ClientInit_CipherCommitment) ProtoReflect() protoreflect.Message { + mi := &file_ukey_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Ukey2ClientInit_CipherCommitment.ProtoReflect.Descriptor instead. +func (*Ukey2ClientInit_CipherCommitment) Descriptor() ([]byte, []int) { + return file_ukey_proto_rawDescGZIP(), []int{2, 0} +} + +func (x *Ukey2ClientInit_CipherCommitment) GetHandshakeCipher() Ukey2HandshakeCipher { + if x != nil { + return x.HandshakeCipher + } + return Ukey2HandshakeCipher_RESERVED +} + +func (x *Ukey2ClientInit_CipherCommitment) GetCommitment() []byte { + if x != nil { + return x.Commitment + } + return nil +} + +var File_ukey_proto protoreflect.FileDescriptor + +//go:embed ukey.pb.raw +var file_ukey_proto_rawDesc []byte + +var ( + file_ukey_proto_rawDescOnce sync.Once + file_ukey_proto_rawDescData = file_ukey_proto_rawDesc +) + +func file_ukey_proto_rawDescGZIP() []byte { + file_ukey_proto_rawDescOnce.Do(func() { + file_ukey_proto_rawDescData = protoimpl.X.CompressGZIP(file_ukey_proto_rawDescData) + }) + return file_ukey_proto_rawDescData +} + +var file_ukey_proto_enumTypes = make([]protoimpl.EnumInfo, 4) +var file_ukey_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_ukey_proto_goTypes = []interface{}{ + (Ukey2HandshakeCipher)(0), // 0: ukey.Ukey2HandshakeCipher + (PublicKeyType)(0), // 1: ukey.PublicKeyType + (Ukey2Message_Type)(0), // 2: ukey.Ukey2Message.Type + (Ukey2Alert_AlertType)(0), // 3: ukey.Ukey2Alert.AlertType + (*Ukey2Message)(nil), // 4: ukey.Ukey2Message + (*Ukey2Alert)(nil), // 5: ukey.Ukey2Alert + (*Ukey2ClientInit)(nil), // 6: ukey.Ukey2ClientInit + (*Ukey2ServerInit)(nil), // 7: ukey.Ukey2ServerInit + (*Ukey2ClientFinished)(nil), // 8: ukey.Ukey2ClientFinished + (*EcP256PublicKey)(nil), // 9: ukey.EcP256PublicKey + (*SimpleRsaPublicKey)(nil), // 10: ukey.SimpleRsaPublicKey + (*DhPublicKey)(nil), // 11: ukey.DhPublicKey + (*GenericPublicKey)(nil), // 12: ukey.GenericPublicKey + (*Ukey2ClientInit_CipherCommitment)(nil), // 13: ukey.Ukey2ClientInit.CipherCommitment +} +var file_ukey_proto_depIdxs = []int32{ + 2, // 0: ukey.Ukey2Message.message_type:type_name -> ukey.Ukey2Message.Type + 3, // 1: ukey.Ukey2Alert.type:type_name -> ukey.Ukey2Alert.AlertType + 13, // 2: ukey.Ukey2ClientInit.cipher_commitments:type_name -> ukey.Ukey2ClientInit.CipherCommitment + 0, // 3: ukey.Ukey2ServerInit.handshake_cipher:type_name -> ukey.Ukey2HandshakeCipher + 12, // 4: ukey.Ukey2ServerInit.public_key:type_name -> ukey.GenericPublicKey + 12, // 5: ukey.Ukey2ClientFinished.public_key:type_name -> ukey.GenericPublicKey + 1, // 6: ukey.GenericPublicKey.type:type_name -> ukey.PublicKeyType + 9, // 7: ukey.GenericPublicKey.ec_p256_public_key:type_name -> ukey.EcP256PublicKey + 10, // 8: ukey.GenericPublicKey.rsa2048_public_key:type_name -> ukey.SimpleRsaPublicKey + 11, // 9: ukey.GenericPublicKey.dh2048_public_key:type_name -> ukey.DhPublicKey + 0, // 10: ukey.Ukey2ClientInit.CipherCommitment.handshake_cipher:type_name -> ukey.Ukey2HandshakeCipher + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name +} + +func init() { file_ukey_proto_init() } +func file_ukey_proto_init() { + if File_ukey_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_ukey_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ukey2Message); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ukey_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ukey2Alert); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ukey_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ukey2ClientInit); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ukey_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ukey2ServerInit); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ukey_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ukey2ClientFinished); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ukey_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EcP256PublicKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ukey_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SimpleRsaPublicKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ukey_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DhPublicKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ukey_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GenericPublicKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_ukey_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ukey2ClientInit_CipherCommitment); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_ukey_proto_msgTypes[8].OneofWrappers = []interface{}{ + (*GenericPublicKey_EcP256PublicKey)(nil), + (*GenericPublicKey_Rsa2048PublicKey)(nil), + (*GenericPublicKey_Dh2048PublicKey)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_ukey_proto_rawDesc, + NumEnums: 4, + NumMessages: 10, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_ukey_proto_goTypes, + DependencyIndexes: file_ukey_proto_depIdxs, + EnumInfos: file_ukey_proto_enumTypes, + MessageInfos: file_ukey_proto_msgTypes, + }.Build() + File_ukey_proto = out.File + file_ukey_proto_rawDesc = nil + file_ukey_proto_goTypes = nil + file_ukey_proto_depIdxs = nil +} diff --git a/libgm/gmproto/ukey.pb.raw b/libgm/gmproto/ukey.pb.raw new file mode 100644 index 0000000..8746963 Binary files /dev/null and b/libgm/gmproto/ukey.pb.raw differ diff --git a/libgm/gmproto/ukey.proto b/libgm/gmproto/ukey.proto new file mode 100644 index 0000000..bd55058 --- /dev/null +++ b/libgm/gmproto/ukey.proto @@ -0,0 +1,117 @@ +syntax = "proto3"; +package ukey; + +option go_package = "../gmproto"; + +message Ukey2Message { + enum Type { + UNKNOWN_DO_NOT_USE = 0; + ALERT = 1; + CLIENT_INIT = 2; + SERVER_INIT = 3; + CLIENT_FINISH = 4; + } + + Type message_type = 1; // Identifies message type + bytes message_data = 2; // Actual message, to be parsed according to message_type +} + +message Ukey2Alert { + enum AlertType { + UNKNOWN_ALERT_TYPE = 0; + // Framing errors + BAD_MESSAGE = 1; // The message could not be deserialized + BAD_MESSAGE_TYPE = 2; // message_type has an undefined value + INCORRECT_MESSAGE = 3; // message_type received does not correspond to expected type at this stage of the protocol + BAD_MESSAGE_DATA = 4; // Could not deserialize message_data as per value in message_type + + // ClientInit and ServerInit errors + BAD_VERSION = 100; // version is invalid; server cannot find suitable version to speak with client. + BAD_RANDOM = 101; // Random data is missing or of incorrect length + BAD_HANDSHAKE_CIPHER = 102; // No suitable handshake ciphers were found + BAD_NEXT_PROTOCOL = 103; // The next protocol is missing, unknown, or unsupported + BAD_PUBLIC_KEY = 104; // The public key could not be parsed + + // Other errors + INTERNAL_ERROR = 200; // An internal error has occurred. error_message may contain additional details for logging and debugging. + } + + AlertType type = 1; + string error_message = 2; +} + +enum Ukey2HandshakeCipher { + RESERVED = 0; + P256_SHA512 = 100; // NIST P-256 used for ECDH, SHA512 used for commitment + CURVE25519_SHA512 = 200; // Curve 25519 used for ECDH, SHA512 used for commitment +} + +message Ukey2ClientInit { + int32 version = 1; // highest supported version for rollback protection + bytes random = 2; // random bytes for replay/reuse protection + + // One commitment (hash of ClientFinished containing public key) per supported cipher + message CipherCommitment { + Ukey2HandshakeCipher handshake_cipher = 1; + bytes commitment = 2; + } + repeated CipherCommitment cipher_commitments = 3; + + // Next protocol that the client wants to speak. + string next_protocol = 4; +} + +message Ukey2ServerInit { + int32 version = 1; // highest supported version for rollback protection + bytes random = 2; // random bytes for replay/reuse protection + + // Selected Cipher and corresponding public key + Ukey2HandshakeCipher handshake_cipher = 3; + GenericPublicKey public_key = 4; +} + +message Ukey2ClientFinished { + GenericPublicKey public_key = 1; // public key matching selected handshake cipher +} + +// A list of supported public key types +enum PublicKeyType { + UNKNOWN_PUBLIC_KEY_TYPE = 0; + EC_P256 = 1; + RSA2048 = 2; + // 2048-bit MODP group 14, from RFC 3526 + DH2048_MODP = 3; +} + +// A convenience proto for encoding NIST P-256 elliptic curve public keys +message EcP256PublicKey { + // x and y are encoded in big-endian two's complement (slightly wasteful) + // Client MUST verify (x,y) is a valid point on NIST P256 + bytes x = 1; + bytes y = 2; +} + +// A convenience proto for encoding RSA public keys with small exponents +message SimpleRsaPublicKey { + // Encoded in big-endian two's complement + bytes n = 1; + int32 e = 2; +} + +// A convenience proto for encoding Diffie-Hellman public keys, +// for use only when Elliptic Curve based key exchanges are not possible. +// (Note that the group parameters must be specified separately) +message DhPublicKey { + // Big-endian two's complement encoded group element + bytes y = 1; +} + +message GenericPublicKey { + PublicKeyType type = 1; + oneof public_key { + EcP256PublicKey ec_p256_public_key = 2; + SimpleRsaPublicKey rsa2048_public_key = 3; + // Use only as a last resort + DhPublicKey dh2048_public_key = 4; + } +} diff --git a/libgm/gmtest/go.mod b/libgm/gmtest/go.mod index f44cafe..ffba760 100644 --- a/libgm/gmtest/go.mod +++ b/libgm/gmtest/go.mod @@ -1,22 +1,21 @@ module go.mau.fi/mautrix-gmessages/libgm/gmtest -go 1.20 +go 1.21 require ( - github.com/mdp/qrterminal/v3 v3.2.0 - github.com/rs/zerolog v1.31.0 + github.com/rs/zerolog v1.32.0 go.mau.fi/mautrix-gmessages/libgm v0.2.2 ) require ( - github.com/google/uuid v1.4.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/term v0.13.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect - rsc.io/qr v0.2.0 // indirect + go.mau.fi/util v0.2.1 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/exp v0.0.0-20240213143201-ec583247a57a // indirect + golang.org/x/sys v0.17.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect ) replace go.mau.fi/mautrix-gmessages/libgm => ../ diff --git a/libgm/gmtest/go.sum b/libgm/gmtest/go.sum index e947ee2..aa1ab00 100644 --- a/libgm/gmtest/go.sum +++ b/libgm/gmtest/go.sum @@ -1,38 +1,37 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mdp/qrterminal/v3 v3.2.0 h1:qteQMXO3oyTK4IHwj2mWsKYYRBOp1Pj2WRYFYYNTCdk= -github.com/mdp/qrterminal/v3 v3.2.0/go.mod h1:XGGuua4Lefrl7TLEsSONiD+UEjQXJZ4mPzF+gWYIJkk= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +go.mau.fi/util v0.2.1 h1:eazulhFE/UmjOFtPrGg6zkF5YfAyiDzQb8ihLMbsPWw= +go.mau.fi/util v0.2.1/go.mod h1:MjlzCQEMzJ+G8RsPawHzpLB8rwTo3aPIjG5FzBvQT/c= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY= -rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/libgm/gmtest/main.go b/libgm/gmtest/main.go index af4254b..100d372 100644 --- a/libgm/gmtest/main.go +++ b/libgm/gmtest/main.go @@ -4,13 +4,13 @@ import ( "bufio" "encoding/json" "errors" + "fmt" "os" "os/signal" "strings" "syscall" "time" - "github.com/mdp/qrterminal/v3" "github.com/rs/zerolog" "go.mau.fi/mautrix-gmessages/libgm" @@ -46,6 +46,8 @@ func main() { } sess = *libgm.NewAuthData() doLogin = true + cookies := mustReturn(os.Open("cookies.json")) + must(json.NewDecoder(cookies).Decode(&sess.Cookies)) } else { must(json.NewDecoder(file).Decode(&sess)) log.Info().Msg("Loaded session?") @@ -54,19 +56,12 @@ func main() { cli = libgm.NewClient(&sess, log) cli.SetEventHandler(evtHandler) if doLogin { - qr := mustReturn(cli.StartLogin()) - qrterminal.GenerateHalfBlock(qr, qrterminal.L, os.Stdout) - go func() { - ticker := time.NewTicker(30 * time.Second) - defer ticker.Stop() - for range ticker.C { - if sess.Browser != nil { - return - } - qr := mustReturn(cli.RefreshPhoneRelay()) - qrterminal.GenerateHalfBlock(qr, qrterminal.L, os.Stdout) - } - }() + err = cli.DoGaiaPairing(func(emoji string) { + fmt.Println(emoji) + }) + if err != nil { + log.Fatal().Err(err).Msg("Failed to pair") + } } else { must(cli.Connect()) } diff --git a/libgm/go.mod b/libgm/go.mod index 3ee3e76..bad76a6 100644 --- a/libgm/go.mod +++ b/libgm/go.mod @@ -1,13 +1,15 @@ module go.mau.fi/mautrix-gmessages/libgm -go 1.20 +go 1.21 require ( - github.com/google/uuid v1.4.0 - github.com/rs/zerolog v1.31.0 + github.com/google/uuid v1.6.0 + github.com/rs/zerolog v1.32.0 github.com/stretchr/testify v1.8.4 - golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa - google.golang.org/protobuf v1.31.0 + go.mau.fi/util v0.2.1 + golang.org/x/crypto v0.19.0 + golang.org/x/exp v0.0.0-20240213143201-ec583247a57a + google.golang.org/protobuf v1.32.0 ) require ( @@ -15,6 +17,6 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.14.0 // indirect + golang.org/x/sys v0.17.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/libgm/go.sum b/libgm/go.sum index 9156392..6ae2f72 100644 --- a/libgm/go.sum +++ b/libgm/go.sum @@ -2,11 +2,10 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -16,21 +15,23 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= -golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +go.mau.fi/util v0.2.1 h1:eazulhFE/UmjOFtPrGg6zkF5YfAyiDzQb8ihLMbsPWw= +go.mau.fi/util v0.2.1/go.mod h1:MjlzCQEMzJ+G8RsPawHzpLB8rwTo3aPIjG5FzBvQT/c= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= +golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/libgm/http.go b/libgm/http.go index a1305b0..4eaf9c3 100644 --- a/libgm/http.go +++ b/libgm/http.go @@ -3,11 +3,13 @@ package libgm import ( "bytes" "context" + "crypto/sha1" "encoding/base64" "fmt" "io" "mime" "net/http" + "time" "github.com/rs/zerolog" "google.golang.org/protobuf/proto" @@ -41,13 +43,43 @@ func (c *Client) makeProtobufHTTPRequest(url string, data proto.Message, content return nil, err } util.BuildRelayHeaders(req, contentType, "*/*") + c.AddCookieHeaders(req) res, reqErr := c.http.Do(req) if reqErr != nil { return res, reqErr } + c.HandleCookieUpdates(res) return res, nil } +func (c *Client) AddCookieHeaders(req *http.Request) { + if c.AuthData == nil || c.AuthData.Cookies == nil { + return + } + for k, v := range c.AuthData.Cookies { + req.AddCookie(&http.Cookie{Name: k, Value: v}) + } + sapisid, ok := c.AuthData.Cookies["SAPISID"] + if ok { + req.Header.Set("Authorization", sapisidHash(util.MessagesBaseURL, sapisid)) + } +} + +func (c *Client) HandleCookieUpdates(resp *http.Response) { + if c.AuthData.Cookies == nil { + return + } + for _, cookie := range resp.Cookies() { + c.AuthData.Cookies[cookie.Name] = cookie.Value + } +} + +func sapisidHash(origin, sapisid string) string { + ts := time.Now().Unix() + hash := sha1.Sum([]byte(fmt.Sprintf("%d %s %s", ts, sapisid, origin))) + return fmt.Sprintf("SAPISIDHASH %d_%x", ts, hash[:]) +} + func decodeProtoResp(body []byte, contentType string, into proto.Message) error { contentType, _, err := mime.ParseMediaType(contentType) if err != nil { @@ -56,7 +88,7 @@ func decodeProtoResp(body []byte, contentType string, into proto.Message) error switch contentType { case ContentTypeProtobuf: return proto.Unmarshal(body, into) - case ContentTypePBLite: + case ContentTypePBLite, "text/plain": return pblite.Unmarshal(body, into) default: return fmt.Errorf("unknown content type %s in response", contentType) diff --git a/libgm/longpoll.go b/libgm/longpoll.go index 7567ae2..47b05d4 100644 --- a/libgm/longpoll.go +++ b/libgm/longpoll.go @@ -122,13 +122,19 @@ func (c *Client) doLongPoll(loggedIn bool) { Auth: &gmproto.AuthMessage{ RequestID: listenReqID, TachyonAuthToken: c.AuthData.TachyonAuthToken, + Network: c.AuthData.AuthNetwork(), ConfigVersion: util.ConfigMessage, }, Unknown: &gmproto.ReceiveMessagesRequest_UnknownEmptyObject2{ Unknown: &gmproto.ReceiveMessagesRequest_UnknownEmptyObject1{}, }, } - resp, err := c.makeProtobufHTTPRequest(util.ReceiveMessagesURL, payload, ContentTypePBLite) + url := util.ReceiveMessagesURL + if c.AuthData.Cookies != nil { + url = util.ReceiveMessagesURLGoogle + payload.Auth.Network = util.GoogleNetwork + } + resp, err := c.makeProtobufHTTPRequest(url, payload, ContentTypePBLite) if err != nil { if loggedIn { c.triggerEvent(&events.ListenTemporaryError{Error: err}) diff --git a/libgm/methods.go b/libgm/methods.go index 6589dfe..3e182d4 100644 --- a/libgm/methods.go +++ b/libgm/methods.go @@ -120,9 +120,9 @@ func (c *Client) SetTyping(convID string) error { func (c *Client) SetActiveSession() error { c.sessionHandler.ResetSessionID() return c.sessionHandler.sendMessageNoResponse(SendMessageParams{ - Action: gmproto.ActionType_GET_UPDATES, - OmitTTL: true, - UseSessionID: true, + Action: gmproto.ActionType_GET_UPDATES, + OmitTTL: true, + RequestID: c.sessionHandler.sessionID, }) } diff --git a/libgm/pair.go b/libgm/pair.go index 95d7961..1a6212b 100644 --- a/libgm/pair.go +++ b/libgm/pair.go @@ -19,7 +19,7 @@ func (c *Client) StartLogin() (string, error) { if err != nil { return "", err } - c.AuthData.TachyonAuthToken = registered.AuthKeyData.TachyonAuthToken + c.updateTachyonAuthToken(registered.GetAuthKeyData()) go c.doLongPoll(false) qr, err := c.GenerateQRCodeData(registered.GetPairingKey()) if err != nil { @@ -54,7 +54,7 @@ func (c *Client) handlePairingEvent(msg *IncomingRPCMessage) { } func (c *Client) completePairing(data *gmproto.PairedData) { - c.updateTachyonAuthToken(data.GetTokenData().GetTachyonAuthToken(), data.GetTokenData().GetTTL()) + c.updateTachyonAuthToken(data.GetTokenData()) c.AuthData.Mobile = data.Mobile c.AuthData.Browser = data.Browser @@ -81,7 +81,7 @@ func (c *Client) RegisterPhoneRelay() (*gmproto.RegisterPhoneRelayResponse, erro payload := &gmproto.AuthenticationContainer{ AuthMessage: &gmproto.AuthMessage{ RequestID: uuid.NewString(), - Network: &util.Network, + Network: util.QRNetwork, ConfigVersion: util.ConfigMessage, }, BrowserDetails: util.BrowserDetailsMessage, @@ -103,7 +103,7 @@ func (c *Client) RefreshPhoneRelay() (string, error) { payload := &gmproto.AuthenticationContainer{ AuthMessage: &gmproto.AuthMessage{ RequestID: uuid.NewString(), - Network: &util.Network, + Network: util.QRNetwork, TachyonAuthToken: c.AuthData.TachyonAuthToken, ConfigVersion: util.ConfigMessage, }, @@ -134,7 +134,7 @@ func (c *Client) GetWebEncryptionKey() (*gmproto.WebEncryptionKeyResponse, error ) } -func (c *Client) Unpair() (*gmproto.RevokeRelayPairingResponse, error) { +func (c *Client) UnpairBugle() (*gmproto.RevokeRelayPairingResponse, error) { if c.AuthData.TachyonAuthToken == nil || c.AuthData.Browser == nil { return nil, nil } @@ -150,3 +150,12 @@ func (c *Client) Unpair() (*gmproto.RevokeRelayPairingResponse, error) { c.makeProtobufHTTPRequest(util.RevokeRelayPairingURL, payload, ContentTypeProtobuf), ) } + +func (c *Client) Unpair() (err error) { + if c.AuthData.Cookies != nil { + err = c.UnpairGaia() + } else { + _, err = c.UnpairBugle() + } + return +} diff --git a/libgm/pair_google.go b/libgm/pair_google.go new file mode 100644 index 0000000..121092a --- /dev/null +++ b/libgm/pair_google.go @@ -0,0 +1,349 @@ +// mautrix-gmessages - A Matrix-Google Messages puppeting bridge. +// Copyright (C) 2024 Tulir Asokan +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package libgm + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/sha256" + "crypto/sha512" + "crypto/x509" + "encoding/binary" + "errors" + "fmt" + "io" + "math/big" + "time" + + "github.com/google/uuid" + "go.mau.fi/util/random" + "golang.org/x/crypto/hkdf" + "google.golang.org/protobuf/proto" + + "go.mau.fi/mautrix-gmessages/libgm/events" + "go.mau.fi/mautrix-gmessages/libgm/gmproto" + "go.mau.fi/mautrix-gmessages/libgm/util" +) + +func (c *Client) handleGaiaPairingEvent(msg *IncomingRPCMessage) { + c.Logger.Debug().Any("evt", msg.Gaia).Msg("Gaia event") +} + +func (c *Client) baseSignInGaiaPayload() *gmproto.SignInGaiaRequest { + return &gmproto.SignInGaiaRequest{ + AuthMessage: &gmproto.AuthMessage{ + RequestID: uuid.NewString(), + Network: util.GoogleNetwork, + ConfigVersion: util.ConfigMessage, + }, + Inner: &gmproto.SignInGaiaRequest_Inner{ + DeviceID: &gmproto.SignInGaiaRequest_Inner_DeviceID{ + UnknownInt1: 3, + DeviceID: fmt.Sprintf("messages-web-%x", c.AuthData.SessionID[:]), + }, + }, + Network: util.GoogleNetwork, + } +} + +func (c *Client) signInGaiaInitial() (*gmproto.SignInGaiaResponse, error) { + payload := c.baseSignInGaiaPayload() + payload.UnknownInt3 = 1 + return typedHTTPResponse[*gmproto.SignInGaiaResponse]( + c.makeProtobufHTTPRequest(util.SignInGaiaURL, payload, ContentTypePBLite), + ) +} + +func (c *Client) signInGaiaGetToken() (*gmproto.SignInGaiaResponse, error) { + key, err := x509.MarshalPKIXPublicKey(c.AuthData.RefreshKey.GetPublicKey()) + if err != nil { + return nil, err + } + + payload := c.baseSignInGaiaPayload() + payload.Inner.SomeData = &gmproto.SignInGaiaRequest_Inner_Data{ + SomeData: key, + } + resp, err := typedHTTPResponse[*gmproto.SignInGaiaResponse]( + c.makeProtobufHTTPRequest(util.SignInGaiaURL, payload, ContentTypePBLite), + ) + if err != nil { + return nil, err + } + c.updateTachyonAuthToken(resp.GetTokenData()) + c.AuthData.Mobile = resp.GetDeviceData().GetDeviceWrapper().GetDevice() + c.AuthData.Browser = resp.GetDeviceData().GetDeviceWrapper().GetDevice() + return resp, nil +} + +type PairingSession struct { + UUID uuid.UUID + Start time.Time + PairingKeyDSA *ecdsa.PrivateKey + InitPayload []byte + NextKey []byte +} + +func NewPairingSession() PairingSession { + ec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + panic(err) + } + return PairingSession{ + UUID: uuid.New(), + Start: time.Now(), + PairingKeyDSA: ec, + } +} + +func (ps *PairingSession) PreparePayloads() ([]byte, []byte, error) { + pubKey := &gmproto.GenericPublicKey{ + Type: gmproto.PublicKeyType_EC_P256, + PublicKey: &gmproto.GenericPublicKey_EcP256PublicKey{ + EcP256PublicKey: &gmproto.EcP256PublicKey{ + X: make([]byte, 33), + Y: make([]byte, 33), + }, + }, + } + ps.PairingKeyDSA.X.FillBytes(pubKey.GetEcP256PublicKey().GetX()[1:]) + ps.PairingKeyDSA.Y.FillBytes(pubKey.GetEcP256PublicKey().GetY()[1:]) + + finishPayload, err := proto.Marshal(&gmproto.Ukey2ClientFinished{ + PublicKey: pubKey, + }) + if err != nil { + return nil, nil, fmt.Errorf("failed to marshal finish payload: %w", err) + } + finish, err := proto.Marshal(&gmproto.Ukey2Message{ + MessageType: gmproto.Ukey2Message_CLIENT_FINISH, + MessageData: finishPayload, + }) + if err != nil { + return nil, nil, fmt.Errorf("failed to marshal finish message: %w", err) + } + + keyCommitment := sha512.Sum512(finish) + initPayload, err := proto.Marshal(&gmproto.Ukey2ClientInit{ + Version: 1, + Random: random.Bytes(32), + CipherCommitments: []*gmproto.Ukey2ClientInit_CipherCommitment{{ + HandshakeCipher: gmproto.Ukey2HandshakeCipher_P256_SHA512, + Commitment: keyCommitment[:], + }}, + NextProtocol: "AES_256_CBC-HMAC_SHA256", + }) + if err != nil { + return nil, nil, fmt.Errorf("failed to marshal init payload: %w", err) + } + init, err := proto.Marshal(&gmproto.Ukey2Message{ + MessageType: gmproto.Ukey2Message_CLIENT_INIT, + MessageData: initPayload, + }) + if err != nil { + return nil, nil, fmt.Errorf("failed to marshal init message: %w", err) + } + ps.InitPayload = init + return init, finish, nil +} + +func doHKDF(key []byte, salt, info []byte) []byte { + h := hkdf.New(sha256.New, key, salt, info) + out := make([]byte, 32) + _, err := io.ReadFull(h, out) + if err != nil { + panic(err) + } + return out +} + +var encryptionKeyInfo = []byte{130, 170, 85, 160, 211, 151, 248, 131, 70, 202, 28, 238, 141, 57, 9, 185, 95, 19, 250, 125, 235, 29, 74, 179, 131, 118, 184, 37, 109, 168, 85, 16} +var pairingEmojis = []string{"๐Ÿ˜", "๐Ÿ˜…", "๐Ÿคฃ", "๐Ÿซ ", "๐Ÿฅฐ", "๐Ÿ˜‡", "๐Ÿคฉ", "๐Ÿ˜˜", "๐Ÿ˜œ", "๐Ÿค—", "๐Ÿค”", "๐Ÿค", "๐Ÿ˜ด", "๐Ÿฅถ", "๐Ÿคฏ", "๐Ÿค ", "๐Ÿฅณ", "๐Ÿฅธ", "๐Ÿ˜Ž", "๐Ÿค“", "๐Ÿง", "๐Ÿฅน", "๐Ÿ˜ญ", "๐Ÿ˜ฑ", "๐Ÿ˜–", "๐Ÿฅฑ", "๐Ÿ˜ฎ\u200d๐Ÿ’จ", "๐Ÿคก", "๐Ÿ’ฉ", "๐Ÿ‘ป", "๐Ÿ‘ฝ", "๐Ÿค–", "๐Ÿ˜ป", "๐Ÿ’Œ", "๐Ÿ’˜", "๐Ÿ’•", "โค", "๐Ÿ’ข", "๐Ÿ’ฅ", "๐Ÿ’ซ", "๐Ÿ’ฌ", "๐Ÿ—ฏ", "๐Ÿ’ค", "๐Ÿ‘‹", "๐Ÿ™Œ", "๐Ÿ™", "โœ", "๐Ÿฆถ", "๐Ÿ‘‚", "๐Ÿง ", "๐Ÿฆด", "๐Ÿ‘€", "๐Ÿง‘", "๐Ÿงš", "๐Ÿง", "๐Ÿ‘ฃ", "๐Ÿต", "๐Ÿถ", "๐Ÿบ", "๐ŸฆŠ", "๐Ÿฆ", "๐Ÿฏ", "๐Ÿฆ“", "๐Ÿฆ„", "๐Ÿ‘", "๐Ÿฎ", "๐Ÿท", "๐Ÿฟ", "๐Ÿฐ", "๐Ÿฆ‡", "๐Ÿป", "๐Ÿจ", "๐Ÿผ", "๐Ÿฆฅ", "๐Ÿพ", "๐Ÿ”", "๐Ÿฅ", "๐Ÿฆ", "๐Ÿ•Š", "๐Ÿฆ†", "๐Ÿฆ‰", "๐Ÿชถ", "๐Ÿฆฉ", "๐Ÿธ", "๐Ÿข", "๐ŸฆŽ", "๐Ÿ", "๐Ÿณ", "๐Ÿฌ", "๐Ÿฆญ", "๐Ÿ ", "๐Ÿก", "๐Ÿฆˆ", "๐Ÿชธ", "๐ŸŒ", "๐Ÿฆ‹", "๐Ÿ›", "๐Ÿ", "๐Ÿž", "๐Ÿชฑ", "๐Ÿ’", "๐ŸŒธ", "๐ŸŒน", "๐ŸŒป", "๐ŸŒฑ", "๐ŸŒฒ", "๐ŸŒด", "๐ŸŒต", "๐ŸŒพ", "โ˜˜", "๐Ÿ", "๐Ÿ‚", "๐Ÿ„", "๐Ÿชบ", "๐Ÿ‡", "๐Ÿˆ", "๐Ÿ‰", "๐Ÿ‹", "๐ŸŒ", "๐Ÿ", "๐ŸŽ", "๐Ÿ", "๐Ÿ’", "๐Ÿ“", "๐Ÿฅ", "๐Ÿฅฅ", "๐Ÿฅ‘", "๐Ÿฅ•", "๐ŸŒฝ", "๐ŸŒถ", "๐Ÿซ‘", "๐Ÿฅฆ", "๐Ÿฅœ", "๐Ÿž", "๐Ÿฅ", "๐Ÿฅจ", "๐Ÿง€", "๐Ÿ—", "๐Ÿ”", "๐ŸŸ", "๐Ÿ•", "๐ŸŒญ", "๐ŸŒฎ", "๐Ÿฅ—", "๐Ÿฅฃ", "๐Ÿฟ", "๐Ÿฆ€", "๐Ÿฆ‘", "๐Ÿฆ", "๐Ÿฉ", "๐Ÿช", "๐Ÿซ", "๐Ÿฐ", "๐Ÿฌ", "๐Ÿญ", "โ˜•", "๐Ÿซ–", "๐Ÿน", "๐Ÿฅค", "๐ŸงŠ", "๐Ÿฅข", "๐Ÿฝ", "๐Ÿฅ„", "๐Ÿงญ", "๐Ÿ”", "๐ŸŒ‹", "๐Ÿ•", "๐Ÿ–", "๐Ÿชต", "๐Ÿ—", "๐Ÿก", "๐Ÿฐ", "๐Ÿ›", "๐Ÿš‚", "๐Ÿ›ต", "๐Ÿ›ด", "๐Ÿ›ผ", "๐Ÿšฅ", "โš“", "๐Ÿ›Ÿ", "โ›ต", "โœˆ", "๐Ÿš€", "๐Ÿ›ธ", "๐Ÿงณ", "โฐ", "๐ŸŒ™", "๐ŸŒก", "๐ŸŒž", "๐Ÿช", "๐ŸŒ ", "๐ŸŒง", "๐ŸŒ€", "๐ŸŒˆ", "โ˜‚", "โšก", "โ„", "โ›„", "๐Ÿ”ฅ", "๐ŸŽ‡", "๐Ÿงจ", "โœจ", "๐ŸŽˆ", "๐ŸŽ‰", "๐ŸŽ", "๐Ÿ†", "๐Ÿ…", "โšฝ", "โšพ", "๐Ÿ€", "๐Ÿ", "๐Ÿˆ", "๐ŸŽพ", "๐ŸŽณ", "๐Ÿ“", "๐ŸฅŠ", "โ›ณ", "โ›ธ", "๐ŸŽฏ", "๐Ÿช", "๐Ÿ”ฎ", "๐ŸŽฎ", "๐Ÿงฉ", "๐Ÿงธ", "๐Ÿชฉ", "๐Ÿ–ผ", "๐ŸŽจ", "๐Ÿงต", "๐Ÿงถ", "๐Ÿฆบ", "๐Ÿงฃ", "๐Ÿงค", "๐Ÿงฆ", "๐ŸŽ’", "๐Ÿฉด", "๐Ÿ‘Ÿ", "๐Ÿ‘‘", "๐Ÿ‘’", "๐ŸŽฉ", "๐Ÿงข", "๐Ÿ’Ž", "๐Ÿ””", "๐ŸŽค", "๐Ÿ“ป", "๐ŸŽท", "๐Ÿช—", "๐ŸŽธ", "๐ŸŽบ", "๐ŸŽป", "๐Ÿฅ", "๐Ÿ“บ", "๐Ÿ”‹", "๐Ÿ’ป", "๐Ÿ’ฟ", "โ˜Ž", "๐Ÿ•ฏ", "๐Ÿ’ก", "๐Ÿ“–", "๐Ÿ“š", "๐Ÿ“ฌ", "โœ", "โœ’", "๐Ÿ–Œ", "๐Ÿ–", "๐Ÿ“", "๐Ÿ’ผ", "๐Ÿ“‹", "๐Ÿ“Œ", "๐Ÿ“Ž", "๐Ÿ”‘", "๐Ÿ”ง", "๐Ÿงฒ", "๐Ÿชœ", "๐Ÿงฌ", "๐Ÿ”ญ", "๐Ÿฉน", "๐Ÿฉบ", "๐Ÿชž", "๐Ÿ›‹", "๐Ÿช‘", "๐Ÿ›", "๐Ÿงน", "๐Ÿงบ", "๐Ÿ”ฑ", "๐Ÿ", "๐Ÿช", "๐Ÿ˜", "๐Ÿฆƒ", "๐Ÿž", "๐Ÿœ", "๐Ÿ ", "๐Ÿš˜", "๐Ÿคฟ", "๐Ÿƒ", "๐Ÿ‘•", "๐Ÿ“ธ", "๐Ÿท", "โœ‚", "๐Ÿงช", "๐Ÿšช", "๐Ÿงด", "๐Ÿงป", "๐Ÿชฃ", "๐Ÿงฝ", "๐Ÿšธ"} + +func (ps *PairingSession) ProcessServerInit(msg *gmproto.GaiaPairingResponseContainer) (string, error) { + var ukeyMessage gmproto.Ukey2Message + err := proto.Unmarshal(msg.GetData(), &ukeyMessage) + if err != nil { + return "", fmt.Errorf("failed to unmarshal server init message: %w", err) + } else if ukeyMessage.GetMessageType() != gmproto.Ukey2Message_SERVER_INIT { + return "", fmt.Errorf("unexpected message type: %v", ukeyMessage.GetMessageType()) + } + var serverInit gmproto.Ukey2ServerInit + err = proto.Unmarshal(ukeyMessage.GetMessageData(), &serverInit) + if err != nil { + return "", fmt.Errorf("failed to unmarshal server init payload: %w", err) + } else if serverInit.GetVersion() != 1 { + return "", fmt.Errorf("unexpected server init version: %d", serverInit.GetVersion()) + } else if serverInit.GetHandshakeCipher() != gmproto.Ukey2HandshakeCipher_P256_SHA512 { + return "", fmt.Errorf("unexpected handshake cipher: %v", serverInit.GetHandshakeCipher()) + } else if len(serverInit.GetRandom()) != 32 { + return "", fmt.Errorf("unexpected random length %d", len(serverInit.GetRandom())) + } + serverKeyData := serverInit.GetPublicKey().GetEcP256PublicKey() + x, y := serverKeyData.GetX(), serverKeyData.GetY() + if len(x) == 33 { + if x[0] != 0 { + return "", fmt.Errorf("server key x coordinate has unexpected prefix: %d", x[0]) + } + x = x[1:] + } + if len(y) == 33 { + if y[0] != 0 { + return "", fmt.Errorf("server key y coordinate has unexpected prefix: %d", y[0]) + } + y = y[1:] + } + serverPairingKeyDSA := &ecdsa.PublicKey{ + Curve: elliptic.P256(), + X: big.NewInt(0).SetBytes(x), + Y: big.NewInt(0).SetBytes(y), + } + serverPairingKeyDH, err := serverPairingKeyDSA.ECDH() + if err != nil { + return "", fmt.Errorf("invalid server key: %w", err) + } + ourPairingKeyDH, err := ps.PairingKeyDSA.ECDH() + if err != nil { + return "", fmt.Errorf("invalid our key: %w", err) + } + diffieHellman, err := ourPairingKeyDH.ECDH(serverPairingKeyDH) + if err != nil { + return "", fmt.Errorf("failed to calculate shared secret: %w", err) + } + sharedSecret := sha256.Sum256(diffieHellman) + authInfo := append(ps.InitPayload, msg.GetData()...) + ukeyV1Auth := doHKDF(sharedSecret[:], []byte("UKEY2 v1 auth"), authInfo) + ps.NextKey = doHKDF(sharedSecret[:], []byte("UKEY2 v1 next"), authInfo) + authNumber := binary.BigEndian.Uint32(ukeyV1Auth) + pairingEmoji := pairingEmojis[int(authNumber)%len(pairingEmojis)] + return pairingEmoji, nil +} + +var ( + ErrNoCookies = errors.New("gaia pairing requires cookies") + ErrNoDevicesFound = errors.New("no devices found for gaia pairing") + ErrIncorrectEmoji = errors.New("user chose incorrect emoji on phone") + ErrPairingCancelled = errors.New("user cancelled pairing on phone") + ErrPairingTimeout = errors.New("pairing timed out") +) + +func (c *Client) DoGaiaPairing(emojiCallback func(string)) error { + if len(c.AuthData.Cookies) == 0 { + return ErrNoCookies + } + sigResp, err := c.signInGaiaGetToken() + if err != nil { + return fmt.Errorf("failed to prepare gaia pairing: %w", err) + } + // TODO multiple devices? + var destRegID string + for _, dev := range sigResp.GetDeviceData().GetUnknownItems2() { + if dev.GetUnknownInt4() == 1 { + destRegID = dev.GetDestOrSourceUUID() + break + } + } + if destRegID == "" { + return ErrNoDevicesFound + } + destRegUUID, err := uuid.Parse(destRegID) + if err != nil { + return fmt.Errorf("failed to parse destination UUID: %w", err) + } + c.AuthData.DestRegID = destRegUUID + go c.doLongPoll(false) + ps := NewPairingSession() + clientInit, clientFinish, err := ps.PreparePayloads() + if err != nil { + return fmt.Errorf("failed to prepare pairing payloads: %w", err) + } + serverInit, err := c.sendGaiaPairingMessage(ps, gmproto.ActionType_CREATE_GAIA_PAIRING_CLIENT_INIT, clientInit) + if err != nil { + return fmt.Errorf("failed to send client init: %w", err) + } + pairingEmoji, err := ps.ProcessServerInit(serverInit) + if err != nil { + return fmt.Errorf("error processing server init: %w", err) + } + emojiCallback(pairingEmoji) + finishResp, err := c.sendGaiaPairingMessage(ps, gmproto.ActionType_CREATE_GAIA_PAIRING_CLIENT_FINISHED, clientFinish) + if finishResp.GetFinishErrorType() != 0 { + switch finishResp.GetFinishErrorCode() { + case 5: + return ErrIncorrectEmoji + case 7: + return ErrPairingCancelled + case 6, 2, 3: + return fmt.Errorf("%w (code: %d/%d)", ErrPairingTimeout, finishResp.GetFinishErrorType(), finishResp.GetFinishErrorCode()) + default: + return fmt.Errorf("unknown error pairing: %d/%d", finishResp.GetFinishErrorType(), finishResp.GetFinishErrorCode()) + } + } + c.AuthData.RequestCrypto.AESKey = doHKDF(ps.NextKey, encryptionKeyInfo, []byte("client")) + c.AuthData.RequestCrypto.HMACKey = doHKDF(ps.NextKey, encryptionKeyInfo, []byte("server")) + c.AuthData.PairingID = ps.UUID + c.triggerEvent(&events.PairSuccessful{}) + + go func() { + // Sleep for a bit to let the phone save the pair data. If we reconnect too quickly, + // the phone won't recognize the session the bridge will get unpaired. + time.Sleep(2 * time.Second) + + err := c.Reconnect() + if err != nil { + c.triggerEvent(&events.ListenFatalError{Error: fmt.Errorf("failed to reconnect after pair success: %w", err)}) + } + }() + return nil +} + +func (c *Client) sendGaiaPairingMessage(sess PairingSession, action gmproto.ActionType, msg []byte) (*gmproto.GaiaPairingResponseContainer, error) { + resp, err := c.sessionHandler.sendMessageWithParams(SendMessageParams{ + Action: action, + Data: &gmproto.GaiaPairingRequestContainer{ + PairingAttemptID: sess.UUID.String(), + BrowserDetails: util.BrowserDetailsMessage, + StartTimestamp: sess.Start.UnixMilli(), + Data: msg, + }, + DontEncrypt: true, + CustomTTL: (300 * time.Second).Microseconds(), + MessageType: gmproto.MessageType_GAIA_2, + + NoPingOnTimeout: true, + }) + if err != nil { + return nil, err + } + var respDat gmproto.GaiaPairingResponseContainer + err = proto.Unmarshal(resp.Message.UnencryptedData, &respDat) + if err != nil { + return nil, err + } + return &respDat, nil +} + +func (c *Client) UnpairGaia() error { + return c.sessionHandler.sendMessageNoResponse(SendMessageParams{ + Action: gmproto.ActionType_UNPAIR_GAIA_PAIRING, + Data: &gmproto.RevokeGaiaPairingRequest{ + PairingAttemptID: c.AuthData.PairingID.String(), + }, + NoPingOnTimeout: true, + }) +} diff --git a/libgm/pblite/deserialize.go b/libgm/pblite/deserialize.go index a568246..e177add 100644 --- a/libgm/pblite/deserialize.go +++ b/libgm/pblite/deserialize.go @@ -4,9 +4,13 @@ import ( "encoding/base64" "encoding/json" "fmt" + "strconv" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" + + "go.mau.fi/mautrix-gmessages/libgm/gmproto" ) func Unmarshal(data []byte, m proto.Message) error { @@ -21,6 +25,12 @@ func Unmarshal(data []byte, m proto.Message) error { return deserializeFromSlice(anyDataArr, m.ProtoReflect()) } +func isPbliteBinary(descriptor protoreflect.FieldDescriptor) bool { + opts := descriptor.Options().(*descriptorpb.FieldOptions) + pbliteBinary, ok := proto.GetExtension(opts, gmproto.E_PbliteBinary).(bool) + return ok && pbliteBinary +} + func deserializeOne(val any, index int, ref protoreflect.Message, insideList protoreflect.List, fieldDescriptor protoreflect.FieldDescriptor) (protoreflect.Value, error) { var num float64 var expectedKind, str string @@ -45,18 +55,33 @@ func deserializeOne(val any, index int, ref protoreflect.Message, insideList pro switch fieldDescriptor.Kind() { case protoreflect.MessageKind: ok = true - nestedData, ok := val.([]any) - if !ok { - return outputVal, fmt.Errorf("expected untyped array at index %d for field %s, got %T", index, fieldDescriptor.FullName(), val) - } var nestedMessage protoreflect.Message if insideList != nil { nestedMessage = insideList.NewElement().Message() } else { nestedMessage = ref.NewField(fieldDescriptor).Message() } - if err := deserializeFromSlice(nestedData, nestedMessage); err != nil { - return outputVal, err + if isPbliteBinary(fieldDescriptor) { + bytesBase64, ok := val.(string) + if !ok { + return outputVal, fmt.Errorf("expected string at index %d for field %s, got %T", index, fieldDescriptor.FullName(), val) + } + bytes, err := base64.StdEncoding.DecodeString(bytesBase64) + if err != nil { + return outputVal, fmt.Errorf("failed to decode base64 at index %d for field %s: %w", index, fieldDescriptor.FullName(), err) + } + err = proto.Unmarshal(bytes, nestedMessage.Interface()) + if err != nil { + return outputVal, fmt.Errorf("failed to unmarshal binary protobuf at index %d for field %s: %w", index, fieldDescriptor.FullName(), err) + } + } else { + nestedData, ok := val.([]any) + if !ok { + return outputVal, fmt.Errorf("expected untyped array at index %d for field %s, got %T", index, fieldDescriptor.FullName(), val) + } + if err := deserializeFromSlice(nestedData, nestedMessage); err != nil { + return outputVal, err + } } outputVal = protoreflect.ValueOfMessage(nestedMessage) case protoreflect.BytesKind: @@ -76,21 +101,53 @@ func deserializeOne(val any, index int, ref protoreflect.Message, insideList pro expectedKind = "float64" outputVal = protoreflect.ValueOfEnum(protoreflect.EnumNumber(int32(num))) case protoreflect.Int32Kind: - num, ok = val.(float64) - expectedKind = "float64" - outputVal = protoreflect.ValueOfInt32(int32(num)) + if str, ok = val.(string); ok { + parsedVal, err := strconv.ParseInt(str, 10, 32) + if err != nil { + return outputVal, fmt.Errorf("failed to parse int32 at index %d for field %s: %w", index, fieldDescriptor.FullName(), err) + } + outputVal = protoreflect.ValueOfInt32(int32(parsedVal)) + } else { + num, ok = val.(float64) + expectedKind = "float64" + outputVal = protoreflect.ValueOfInt32(int32(num)) + } case protoreflect.Int64Kind: - num, ok = val.(float64) - expectedKind = "float64" - outputVal = protoreflect.ValueOfInt64(int64(num)) + if str, ok = val.(string); ok { + parsedVal, err := strconv.ParseInt(str, 10, 64) + if err != nil { + return outputVal, fmt.Errorf("failed to parse int64 at index %d for field %s: %w", index, fieldDescriptor.FullName(), err) + } + outputVal = protoreflect.ValueOfInt64(parsedVal) + } else { + num, ok = val.(float64) + expectedKind = "float64" + outputVal = protoreflect.ValueOfInt64(int64(num)) + } case protoreflect.Uint32Kind: - num, ok = val.(float64) - expectedKind = "float64" - outputVal = protoreflect.ValueOfUint32(uint32(num)) + if str, ok = val.(string); ok { + parsedVal, err := strconv.ParseUint(str, 10, 32) + if err != nil { + return outputVal, fmt.Errorf("failed to parse uint32 at index %d for field %s: %w", index, fieldDescriptor.FullName(), err) + } + outputVal = protoreflect.ValueOfUint32(uint32(parsedVal)) + } else { + num, ok = val.(float64) + expectedKind = "float64" + outputVal = protoreflect.ValueOfUint32(uint32(num)) + } case protoreflect.Uint64Kind: - num, ok = val.(float64) - expectedKind = "float64" - outputVal = protoreflect.ValueOfUint64(uint64(num)) + if str, ok = val.(string); ok { + parsedVal, err := strconv.ParseUint(str, 10, 64) + if err != nil { + return outputVal, fmt.Errorf("failed to parse uint64 at index %d for field %s: %w", index, fieldDescriptor.FullName(), err) + } + outputVal = protoreflect.ValueOfUint64(parsedVal) + } else { + num, ok = val.(float64) + expectedKind = "float64" + outputVal = protoreflect.ValueOfUint64(uint64(num)) + } case protoreflect.FloatKind: num, ok = val.(float64) expectedKind = "float64" @@ -101,6 +158,13 @@ func deserializeOne(val any, index int, ref protoreflect.Message, insideList pro outputVal = protoreflect.ValueOfFloat64(num) case protoreflect.StringKind: str, ok = val.(string) + if ok && isPbliteBinary(fieldDescriptor) { + bytes, err := base64.StdEncoding.DecodeString(str) + if err != nil { + return outputVal, fmt.Errorf("failed to decode base64 at index %d for field %s: %w", index, fieldDescriptor.FullName(), err) + } + str = string(bytes) + } expectedKind = "string" outputVal = protoreflect.ValueOfString(str) case protoreflect.BoolKind: diff --git a/libgm/pblite/serialize.go b/libgm/pblite/serialize.go index 7bcf86b..5c5db64 100644 --- a/libgm/pblite/serialize.go +++ b/libgm/pblite/serialize.go @@ -82,11 +82,19 @@ func serializeOneOrList(fieldDescriptor protoreflect.FieldDescriptor, fieldValue func serializeOne(fieldDescriptor protoreflect.FieldDescriptor, fieldValue protoreflect.Value) (any, error) { switch fieldDescriptor.Kind() { case protoreflect.MessageKind: - serializedMsg, err := SerializeToSlice(fieldValue.Message().Interface()) - if err != nil { - return nil, err + if isPbliteBinary(fieldDescriptor) { + serializedMsg, err := proto.Marshal(fieldValue.Message().Interface()) + if err != nil { + return nil, err + } + return base64.StdEncoding.EncodeToString(serializedMsg), nil + } else { + serializedMsg, err := SerializeToSlice(fieldValue.Message().Interface()) + if err != nil { + return nil, err + } + return serializedMsg, nil } - return serializedMsg, nil case protoreflect.BytesKind: return base64.StdEncoding.EncodeToString(fieldValue.Bytes()), nil case protoreflect.Int32Kind, protoreflect.Int64Kind: @@ -100,7 +108,11 @@ func serializeOne(fieldDescriptor protoreflect.FieldDescriptor, fieldValue proto case protoreflect.BoolKind: return fieldValue.Bool(), nil case protoreflect.StringKind: - return fieldValue.String(), nil + if isPbliteBinary(fieldDescriptor) { + return base64.StdEncoding.EncodeToString([]byte(fieldValue.String())), nil + } else { + return fieldValue.String(), nil + } default: return nil, fmt.Errorf("unsupported field type %s in %s", fieldDescriptor.Kind(), fieldDescriptor.FullName()) } diff --git a/libgm/pblitedecode/main.go b/libgm/pblitedecode/main.go new file mode 100644 index 0000000..17c95fe --- /dev/null +++ b/libgm/pblitedecode/main.go @@ -0,0 +1,54 @@ +package main + +import ( + "fmt" + "io" + "os" + + "google.golang.org/protobuf/encoding/prototext" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/dynamicpb" + + "go.mau.fi/mautrix-gmessages/libgm/gmproto" + "go.mau.fi/mautrix-gmessages/libgm/pblite" +) + +func must[T any](t T, err error) T { + if err != nil { + panic(err) + } + return t +} + +func main() { + files := []protoreflect.FileDescriptor{ + gmproto.File_authentication_proto, + gmproto.File_config_proto, + gmproto.File_client_proto, + gmproto.File_conversations_proto, + gmproto.File_events_proto, + gmproto.File_rpc_proto, + gmproto.File_settings_proto, + gmproto.File_util_proto, + gmproto.File_ukey_proto, + } + var msgDesc protoreflect.MessageDescriptor + for _, file := range files { + msgDesc = file.Messages().ByName(protoreflect.Name(os.Args[1])) + if msgDesc != nil { + break + } + } + if msgDesc == nil { + fmt.Println("Message not found") + os.Exit(1) + } + msg := dynamicpb.NewMessage(msgDesc) + + err := pblite.Unmarshal(must(io.ReadAll(os.Stdin)), msg) + if err != nil { + fmt.Println(err) + os.Exit(2) + } + fmt.Println(prototext.Format(msg)) +} diff --git a/libgm/session_handler.go b/libgm/session_handler.go index b2e8978..1d7fed0 100644 --- a/libgm/session_handler.go +++ b/libgm/session_handler.go @@ -37,8 +37,12 @@ func (s *SessionHandler) sendMessageNoResponse(params SendMessageParams) error { return err } + url := util.SendMessageURL + if s.client.AuthData.Cookies != nil { + url = util.SendMessageURLGoogle + } _, err = typedHTTPResponse[*gmproto.OutgoingRPCResponse]( - s.client.makeProtobufHTTPRequest(util.SendMessageURL, payload, ContentTypePBLite), + s.client.makeProtobufHTTPRequest(url, payload, ContentTypePBLite), ) return err } @@ -50,8 +54,12 @@ func (s *SessionHandler) sendAsyncMessage(params SendMessageParams) (<-chan *Inc } ch := s.waitResponse(requestID) + url := util.SendMessageURL + if s.client.AuthData.Cookies != nil { + url = util.SendMessageURLGoogle + } _, err = typedHTTPResponse[*gmproto.OutgoingRPCResponse]( - s.client.makeProtobufHTTPRequest(util.SendMessageURL, payload, ContentTypePBLite), + s.client.makeProtobufHTTPRequest(url, payload, ContentTypePBLite), ) if err != nil { s.cancelResponse(requestID, ch) @@ -68,7 +76,7 @@ func typedResponse[T proto.Message](resp *IncomingRPCMessage, err error) (casted var ok bool casted, ok = resp.DecryptedMessage.(T) if !ok { - retErr = fmt.Errorf("unexpected response type %T, expected %T", resp.DecryptedMessage, casted) + retErr = fmt.Errorf("unexpected response type %T for %s, expected %T", resp.DecryptedMessage, resp.ResponseID, casted) } return } @@ -92,6 +100,17 @@ func (s *SessionHandler) receiveResponse(msg *IncomingRPCMessage) bool { if msg.Message == nil { return false } + if s.client.AuthData.Cookies != nil { + switch msg.Message.Action { + case gmproto.ActionType_CREATE_GAIA_PAIRING_CLIENT_INIT, gmproto.ActionType_CREATE_GAIA_PAIRING_CLIENT_FINISHED: + default: + // Very hacky way to ignore weird messages that come before real responses + // TODO figure out how to properly handle these + if msg.Message.UnencryptedData != nil && msg.Message.EncryptedData == nil { + return false + } + } + } requestID := msg.Message.SessionID s.responseWaitersLock.Lock() ch, ok := s.responseWaiters[requestID] @@ -122,6 +141,10 @@ func (s *SessionHandler) sendMessageWithParams(params SendMessageParams) (*Incom return nil, err } + if params.NoPingOnTimeout { + return <-ch, nil + } + select { case resp := <-ch: return resp, nil @@ -147,19 +170,21 @@ type SendMessageParams struct { Action gmproto.ActionType Data proto.Message - UseSessionID bool - OmitTTL bool - MessageType gmproto.MessageType + RequestID string + OmitTTL bool + CustomTTL int64 + DontEncrypt bool + MessageType gmproto.MessageType + + NoPingOnTimeout bool } func (s *SessionHandler) buildMessage(params SendMessageParams) (string, proto.Message, error) { - var requestID string var err error sessionID := s.client.sessionHandler.sessionID - if params.UseSessionID { - requestID = s.sessionID - } else { + requestID := params.RequestID + if requestID == "" { requestID = uuid.NewString() } @@ -182,28 +207,38 @@ func (s *SessionHandler) buildMessage(params SendMessageParams) (string, proto.M TachyonAuthToken: s.client.AuthData.TachyonAuthToken, ConfigVersion: util.ConfigMessage, }, - EmptyArr: &gmproto.EmptyArr{}, + DestRegistrationIDs: []string{}, } - if !params.OmitTTL { + if s.client.AuthData != nil && s.client.AuthData.DestRegID != uuid.Nil { + message.DestRegistrationIDs = append(message.DestRegistrationIDs, s.client.AuthData.DestRegID.String()) + } + if params.CustomTTL != 0 { + message.TTL = params.CustomTTL + } else if !params.OmitTTL { message.TTL = s.client.AuthData.TachyonTTL } - var encryptedData []byte + var encryptedData, unencryptedData []byte if params.Data != nil { var serializedData []byte serializedData, err = proto.Marshal(params.Data) if err != nil { return "", nil, err } - encryptedData, err = s.client.AuthData.RequestCrypto.Encrypt(serializedData) - if err != nil { - return "", nil, err + if params.DontEncrypt { + unencryptedData = serializedData + } else { + encryptedData, err = s.client.AuthData.RequestCrypto.Encrypt(serializedData) + if err != nil { + return "", nil, err + } } } message.Data.MessageData, err = proto.Marshal(&gmproto.OutgoingRPCData{ - RequestID: requestID, - Action: params.Action, - EncryptedProtoData: encryptedData, - SessionID: sessionID, + RequestID: requestID, + Action: params.Action, + UnencryptedProtoData: unencryptedData, + EncryptedProtoData: encryptedData, + SessionID: sessionID, }) if err != nil { return "", nil, err @@ -255,13 +290,18 @@ func (s *SessionHandler) sendAckRequest() { AuthData: &gmproto.AuthMessage{ RequestID: uuid.NewString(), TachyonAuthToken: s.client.AuthData.TachyonAuthToken, + Network: s.client.AuthData.AuthNetwork(), ConfigVersion: util.ConfigMessage, }, EmptyArr: &gmproto.EmptyArr{}, Acks: ackMessages, } + url := util.AckMessagesURL + if s.client.AuthData.Cookies != nil { + url = util.AckMessagesURLGoogle + } _, err := typedHTTPResponse[*gmproto.OutgoingRPCResponse]( - s.client.makeProtobufHTTPRequest(util.AckMessagesURL, payload, ContentTypePBLite), + s.client.makeProtobufHTTPRequest(url, payload, ContentTypePBLite), ) if err != nil { // TODO retry? diff --git a/libgm/util/config.go b/libgm/util/config.go index 70c7969..ac1665c 100644 --- a/libgm/util/config.go +++ b/libgm/util/config.go @@ -5,13 +5,16 @@ import ( ) var ConfigMessage = &gmproto.ConfigVersion{ - Year: 2023, - Month: 9, - Day: 28, + Year: 2024, + Month: 2, + Day: 20, V1: 4, V2: 6, } -var Network = "Bugle" + +const QRNetwork = "Bugle" +const GoogleNetwork = "GDitto" + var BrowserDetailsMessage = &gmproto.BrowserDetails{ UserAgent: UserAgent, BrowserType: gmproto.BrowserType_OTHER, diff --git a/libgm/util/constants.go b/libgm/util/constants.go index 0cb81e3..0719f55 100644 --- a/libgm/util/constants.go +++ b/libgm/util/constants.go @@ -1,7 +1,7 @@ package util const GoogleAPIKey = "AIzaSyCA4RsOZUFrm9whhtGosPlJLmVPnfSHKz8" -const UserAgent = "Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36" +const UserAgent = "Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36" const SecUA = `"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"` const UAPlatform = "Android" const XUserAgent = "grpc-web-javascript/0.1" diff --git a/libgm/util/func.go b/libgm/util/func.go index 9b0c8e3..a749b3a 100644 --- a/libgm/util/func.go +++ b/libgm/util/func.go @@ -1,14 +1,10 @@ package util import ( - "encoding/json" "fmt" "math/rand" "net/http" - "strconv" "time" - - "go.mau.fi/mautrix-gmessages/libgm/gmproto" ) func GenerateTmpID() string { @@ -19,119 +15,71 @@ func GenerateTmpID() string { } func BuildRelayHeaders(req *http.Request, contentType string, accept string) { - req.Header.Add("host", "instantmessaging-pa.googleapis.com") - req.Header.Add("connection", "keep-alive") - req.Header.Add("sec-ch-ua", SecUA) - req.Header.Add("x-user-agent", XUserAgent) - req.Header.Add("x-goog-api-key", GoogleAPIKey) + //req.Header.Set("host", "instantmessaging-pa.googleapis.com") + req.Header.Set("sec-ch-ua", SecUA) + req.Header.Set("x-user-agent", XUserAgent) + req.Header.Set("x-goog-api-key", GoogleAPIKey) if len(contentType) > 0 { - req.Header.Add("content-type", contentType) + req.Header.Set("content-type", contentType) } - req.Header.Add("sec-ch-ua-mobile", SecUAMobile) - req.Header.Add("user-agent", UserAgent) - req.Header.Add("sec-ch-ua-platform", "\""+UAPlatform+"\"") - req.Header.Add("accept", accept) - req.Header.Add("origin", "https://messages.google.com") - req.Header.Add("sec-fetch-site", "cross-site") - req.Header.Add("sec-fetch-mode", "cors") - req.Header.Add("sec-fetch-dest", "empty") - req.Header.Add("referer", "https://messages.google.com/") - req.Header.Add("accept-language", "en-US,en;q=0.9") + req.Header.Set("sec-ch-ua-mobile", SecUAMobile) + req.Header.Set("user-agent", UserAgent) + req.Header.Set("sec-ch-ua-platform", "\""+UAPlatform+"\"") + req.Header.Set("accept", accept) + req.Header.Set("origin", "https://messages.google.com") + req.Header.Set("sec-fetch-site", "cross-site") + req.Header.Set("sec-fetch-mode", "cors") + req.Header.Set("sec-fetch-dest", "empty") + req.Header.Set("referer", "https://messages.google.com/") + req.Header.Set("accept-language", "en-US,en;q=0.9") } func BuildUploadHeaders(req *http.Request, metadata string) { - req.Header.Add("host", "instantmessaging-pa.googleapis.com") - req.Header.Add("connection", "keep-alive") - req.Header.Add("x-goog-download-metadata", metadata) - req.Header.Add("sec-ch-ua", SecUA) - req.Header.Add("sec-ch-ua-mobile", SecUAMobile) - req.Header.Add("user-agent", UserAgent) - req.Header.Add("sec-ch-ua-platform", "\""+UAPlatform+"\"") - req.Header.Add("accept", "*/*") - req.Header.Add("origin", "https://messages.google.com") - req.Header.Add("sec-fetch-site", "cross-site") - req.Header.Add("sec-fetch-mode", "cors") - req.Header.Add("sec-fetch-dest", "empty") - req.Header.Add("referer", "https://messages.google.com/") - req.Header.Add("accept-encoding", "gzip, deflate, br") - req.Header.Add("accept-language", "en-US,en;q=0.9") + //req.Header.Set("host", "instantmessaging-pa.googleapis.com") + req.Header.Set("x-goog-download-metadata", metadata) + req.Header.Set("sec-ch-ua", SecUA) + req.Header.Set("sec-ch-ua-mobile", SecUAMobile) + req.Header.Set("user-agent", UserAgent) + req.Header.Set("sec-ch-ua-platform", "\""+UAPlatform+"\"") + req.Header.Set("accept", "*/*") + req.Header.Set("origin", "https://messages.google.com") + req.Header.Set("sec-fetch-site", "cross-site") + req.Header.Set("sec-fetch-mode", "cors") + req.Header.Set("sec-fetch-dest", "empty") + req.Header.Set("referer", "https://messages.google.com/") + req.Header.Set("accept-encoding", "gzip, deflate, br") + req.Header.Set("accept-language", "en-US,en;q=0.9") } func NewMediaUploadHeaders(imageSize string, command string, uploadOffset string, imageContentType string, protocol string) *http.Header { headers := &http.Header{} - headers.Add("host", "instantmessaging-pa.googleapis.com") - headers.Add("connection", "keep-alive") - headers.Add("sec-ch-ua", SecUA) + headers.Set("host", "instantmessaging-pa.googleapis.com") + headers.Set("sec-ch-ua", SecUA) if protocol != "" { - headers.Add("x-goog-upload-protocol", protocol) + headers.Set("x-goog-upload-protocol", protocol) } - headers.Add("x-goog-upload-header-content-length", imageSize) - headers.Add("sec-ch-ua-mobile", SecUAMobile) - headers.Add("user-agent", UserAgent) + headers.Set("x-goog-upload-header-content-length", imageSize) + headers.Set("sec-ch-ua-mobile", SecUAMobile) + headers.Set("user-agent", UserAgent) if imageContentType != "" { - headers.Add("x-goog-upload-header-content-type", imageContentType) + headers.Set("x-goog-upload-header-content-type", imageContentType) } - headers.Add("content-type", "application/x-www-form-urlencoded;charset=UTF-8") + headers.Set("content-type", "application/x-www-form-urlencoded;charset=UTF-8") if command != "" { - headers.Add("x-goog-upload-command", command) + headers.Set("x-goog-upload-command", command) } if uploadOffset != "" { - headers.Add("x-goog-upload-offset", uploadOffset) + headers.Set("x-goog-upload-offset", uploadOffset) } - headers.Add("sec-ch-ua-platform", "\""+UAPlatform+"\"") - headers.Add("accept", "*/*") - headers.Add("origin", "https://messages.google.com") - headers.Add("sec-fetch-site", "cross-site") - headers.Add("sec-fetch-mode", "cors") - headers.Add("sec-fetch-dest", "empty") - headers.Add("referer", "https://messages.google.com/") - headers.Add("accept-encoding", "gzip, deflate, br") - headers.Add("accept-language", "en-US,en;q=0.9") + headers.Set("sec-ch-ua-platform", "\""+UAPlatform+"\"") + headers.Set("accept", "*/*") + headers.Set("origin", "https://messages.google.com") + headers.Set("sec-fetch-site", "cross-site") + headers.Set("sec-fetch-mode", "cors") + headers.Set("sec-fetch-dest", "empty") + headers.Set("referer", "https://messages.google.com/") + headers.Set("accept-encoding", "gzip, deflate, br") + headers.Set("accept-language", "en-US,en;q=0.9") return headers } - -func ParseConfigVersion(res []byte) (*gmproto.ConfigVersion, error) { - var data []interface{} - - marshalErr := json.Unmarshal(res, &data) - if marshalErr != nil { - return nil, marshalErr - } - - version := data[0].(string) - v1 := version[0:4] - v2 := version[4:6] - v3 := version[6:8] - - if v2[0] == 48 { - v2 = string(v2[1]) - } - if v3[0] == 48 { - v3 = string(v3[1]) - } - - first, e := strconv.Atoi(v1) - if e != nil { - return nil, e - } - - second, e1 := strconv.Atoi(v2) - if e1 != nil { - return nil, e1 - } - - third, e2 := strconv.Atoi(v3) - if e2 != nil { - return nil, e2 - } - - configMessage := &gmproto.ConfigVersion{ - Year: int32(first), - Month: int32(second), - Day: int32(third), - V1: 4, - V2: 6, - } - return configMessage, nil -} diff --git a/libgm/util/paths.go b/libgm/util/paths.go index da7fd69..e05ab22 100644 --- a/libgm/util/paths.go +++ b/libgm/util/paths.go @@ -1,26 +1,32 @@ package util -const messagesBaseURL = "https://messages.google.com" +const MessagesBaseURL = "https://messages.google.com" -const GoogleAuthenticationURL = messagesBaseURL + "/web/authentication" -const GoogleTimesourceURL = messagesBaseURL + "/web/timesource" +const GoogleAuthenticationURL = MessagesBaseURL + "/web/authentication" +const GoogleTimesourceURL = MessagesBaseURL + "/web/timesource" -const instantMessangingBaseURL = "https://instantmessaging-pa.googleapis.com" +const instantMessagingBaseURL = "https://instantmessaging-pa.googleapis.com" +const instantMessagingBaseURLGoogle = "https://instantmessaging-pa.clients6.google.com" -const UploadMediaURL = instantMessangingBaseURL + "/upload" +const UploadMediaURL = instantMessagingBaseURL + "/upload" -const pairingBaseURL = instantMessangingBaseURL + "/$rpc/google.internal.communications.instantmessaging.v1.Pairing" +const pairingBaseURL = instantMessagingBaseURL + "/$rpc/google.internal.communications.instantmessaging.v1.Pairing" const RegisterPhoneRelayURL = pairingBaseURL + "/RegisterPhoneRelay" const RefreshPhoneRelayURL = pairingBaseURL + "/RefreshPhoneRelay" const GetWebEncryptionKeyURL = pairingBaseURL + "/GetWebEncryptionKey" const RevokeRelayPairingURL = pairingBaseURL + "/RevokeRelayPairing" -const messagingBaseURL = instantMessangingBaseURL + "/$rpc/google.internal.communications.instantmessaging.v1.Messaging" +const messagingBaseURL = instantMessagingBaseURL + "/$rpc/google.internal.communications.instantmessaging.v1.Messaging" +const messagingBaseURLGoogle = instantMessagingBaseURLGoogle + "/$rpc/google.internal.communications.instantmessaging.v1.Messaging" const ReceiveMessagesURL = messagingBaseURL + "/ReceiveMessages" const SendMessageURL = messagingBaseURL + "/SendMessage" const AckMessagesURL = messagingBaseURL + "/AckMessages" +const ReceiveMessagesURLGoogle = messagingBaseURLGoogle + "/ReceiveMessages" +const SendMessageURLGoogle = messagingBaseURLGoogle + "/SendMessage" +const AckMessagesURLGoogle = messagingBaseURLGoogle + "/AckMessages" -const registrationBaseURL = instantMessangingBaseURL + "/$rpc/google.internal.communications.instantmessaging.v1.Registration" +const registrationBaseURL = instantMessagingBaseURLGoogle + "/$rpc/google.internal.communications.instantmessaging.v1.Registration" +const SignInGaiaURL = registrationBaseURL + "/SignInGaia" const RegisterRefreshURL = registrationBaseURL + "/RegisterRefresh" const ConfigURL = "https://messages.google.com/web/config" diff --git a/provisioning.go b/provisioning.go index 890b667..d32b722 100644 --- a/provisioning.go +++ b/provisioning.go @@ -51,6 +51,8 @@ func (prov *ProvisioningAPI) Init() { r.Use(prov.AuthMiddleware) r.HandleFunc("/v1/ping", prov.Ping).Methods(http.MethodGet) r.HandleFunc("/v1/login", prov.Login).Methods(http.MethodPost) + r.HandleFunc("/v1/google_login/emoji", prov.GoogleLoginStart).Methods(http.MethodPost) + r.HandleFunc("/v1/google_login/wait", prov.GoogleLoginWait).Methods(http.MethodPost) r.HandleFunc("/v1/logout", prov.Logout).Methods(http.MethodPost) r.HandleFunc("/v1/delete_session", prov.DeleteSession).Methods(http.MethodPost) r.HandleFunc("/v1/disconnect", prov.Disconnect).Methods(http.MethodPost) @@ -309,6 +311,68 @@ func (prov *ProvisioningAPI) Logout(w http.ResponseWriter, r *http.Request) { jsonResponse(w, http.StatusOK, Response{true, "Logged out successfully."}) } +type ReqGoogleLoginStart struct { + Cookies map[string]string +} + +type RespGoogleLoginStart struct { + Status string `json:"status"` + Emoji string `json:"emoji"` +} + +func (prov *ProvisioningAPI) GoogleLoginStart(w http.ResponseWriter, r *http.Request) { + userID := r.URL.Query().Get("user_id") + user := prov.bridge.GetUserByMXID(id.UserID(userID)) + + log := prov.zlog.With().Str("user_id", user.MXID.String()).Str("endpoint", "login").Logger() + + if user.IsLoggedIn() { + jsonResponse(w, http.StatusOK, LoginResponse{Status: "success", ErrCode: "already logged in"}) + return + } + var req ReqGoogleLoginStart + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + jsonResponse(w, http.StatusBadRequest, Error{ + Error: "Failed to parse request JSON", + ErrCode: "bad json", + }) + } + emoji, err := user.AsyncLoginGoogleStart(req.Cookies) + if err != nil { + log.Err(err).Msg("Failed to start login") + // TODO proper error codes + jsonResponse(w, http.StatusInternalServerError, Error{ + Error: "Failed to start login", + ErrCode: "start login fail", + }) + return + } + jsonResponse(w, http.StatusOK, &RespGoogleLoginStart{Status: "emoji", Emoji: emoji}) +} + +func (prov *ProvisioningAPI) GoogleLoginWait(w http.ResponseWriter, r *http.Request) { + userID := r.URL.Query().Get("user_id") + user := prov.bridge.GetUserByMXID(id.UserID(userID)) + + log := prov.zlog.With().Str("user_id", user.MXID.String()).Str("endpoint", "login").Logger() + + if user.IsLoggedIn() { + jsonResponse(w, http.StatusOK, LoginResponse{Status: "success", ErrCode: "already logged in"}) + return + } + err := user.AsyncLoginGoogleWait() + if err != nil { + log.Err(err).Msg("Failed to start login") + // TODO proper error codes + jsonResponse(w, http.StatusInternalServerError, Error{ + Error: "Failed to finish login", + ErrCode: "finish login fail", + }) + return + } + jsonResponse(w, http.StatusOK, LoginResponse{Status: "success"}) +} + type LoginResponse struct { Status string `json:"status"` Code string `json:"code,omitempty"` diff --git a/user.go b/user.go index f6468d8..98aa19a 100644 --- a/user.go +++ b/user.go @@ -35,6 +35,7 @@ import ( "maunium.net/go/mautrix/appservice" "maunium.net/go/mautrix/bridge" "maunium.net/go/mautrix/bridge/bridgeconfig" + "maunium.net/go/mautrix/bridge/commands" "maunium.net/go/mautrix/bridge/status" "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/format" @@ -64,7 +65,8 @@ type User struct { spaceCreateLock sync.Mutex connLock sync.Mutex - BridgeState *bridge.BridgeStateQueue + BridgeState *bridge.BridgeStateQueue + CommandState *commands.CommandState spaceMembershipChecked bool @@ -80,16 +82,27 @@ type User struct { pollErrorAlertSent bool phoneNotRespondingAlertSent bool - loginInProgress atomic.Bool - pairSuccessChan chan struct{} - ongoingLoginChan <-chan qrChannelItem - loginChanReadLock sync.Mutex - lastQRCode string - cancelLogin func() + loginInProgress atomic.Bool + pairSuccessChan chan struct{} + ongoingLoginChan <-chan qrChannelItem + lastQRCode string + cancelLogin func() + + googleAsyncPairErrChan atomic.Pointer[chan error] DoublePuppetIntent *appservice.IntentAPI } +func (user *User) GetCommandState() *commands.CommandState { + return user.CommandState +} + +func (user *User) SetCommandState(state *commands.CommandState) { + user.CommandState = state +} + +var _ commands.CommandingUser = (*User)(nil) + func (br *GMBridge) getUserByMXID(userID id.UserID, onlyIfExists bool) *User { _, isPuppet := br.ParsePuppetMXID(userID) if isPuppet || userID == br.Bot.UserID { @@ -155,10 +168,6 @@ func (user *User) GetMXID() id.UserID { return user.MXID } -func (user *User) GetCommandState() map[string]interface{} { - return nil -} - func (br *GMBridge) GetUserByMXIDIfExists(userID id.UserID) *User { return br.getUserByMXID(userID, true) } @@ -456,6 +465,71 @@ func (user *User) Login(maxAttempts int) (<-chan qrChannelItem, error) { return ch, nil } +func (user *User) AsyncLoginGoogleStart(cookies map[string]string) (outEmoji string, outErr error) { + errChan := make(chan error, 1) + if !user.googleAsyncPairErrChan.CompareAndSwap(nil, &errChan) { + close(errChan) + outErr = fmt.Errorf("login already in progress") + return + } + var callbackDone bool + var initialWait sync.WaitGroup + initialWait.Add(1) + callback := func(emoji string) { + callbackDone = true + outEmoji = emoji + initialWait.Done() + } + go func() { + err := user.LoginGoogle(cookies, callback) + if !callbackDone { + initialWait.Done() + outErr = err + close(errChan) + user.googleAsyncPairErrChan.Store(nil) + } else { + errChan <- err + } + }() + initialWait.Wait() + return +} + +func (user *User) AsyncLoginGoogleWait() error { + ch := user.googleAsyncPairErrChan.Swap(nil) + if ch == nil { + return fmt.Errorf("no login in progress") + } + return <-*ch +} + +func (user *User) LoginGoogle(cookies map[string]string, emojiCallback func(string)) error { + user.connLock.Lock() + defer user.connLock.Unlock() + if user.Session != nil { + return ErrAlreadyLoggedIn + } else if !user.loginInProgress.CompareAndSwap(false, true) { + return ErrLoginInProgress + } + if user.Client != nil { + user.unlockedDeleteConnection() + } + pairSuccessChan := make(chan struct{}) + user.pairSuccessChan = pairSuccessChan + authData := libgm.NewAuthData() + authData.Cookies = cookies + user.createClient(authData) + Analytics.Track(user.MXID, "$login_start") + err := user.Client.DoGaiaPairing(emojiCallback) + if err != nil { + user.unlockedDeleteConnection() + user.pairSuccessChan = nil + user.loginInProgress.Store(false) + return fmt.Errorf("failed to connect to Google Messages: %w", err) + } + return nil +} + func (user *User) Connect() bool { user.connLock.Lock() defer user.connLock.Unlock() @@ -637,6 +711,13 @@ func (user *User) syncHandleEvent(event any) { Error: GMUnpaired, }, false) go user.sendMarkdownBridgeAlert(true, "Unpaired from Google Messages. Log in again to continue using the bridge.") + case *events.GaiaLoggedOut: + user.zlog.Info().Msg("Got gaia logout event") + go user.Logout(status.BridgeState{ + StateEvent: status.StateBadCredentials, + Error: GMUnpaired, + }, false) + go user.sendMarkdownBridgeAlert(true, "Unpaired from Google Messages. Log in again to continue using the bridge.") case *events.AuthTokenRefreshed: go func() { err := user.Update(context.TODO()) @@ -731,9 +812,9 @@ func (user *User) handleAccountChange(v *events.AccountChange) { user.switchedToGoogleLogin = v.GetEnabled() || v.IsFake if !v.IsFake { if user.switchedToGoogleLogin { - go user.sendMarkdownBridgeAlert(true, "The bridge will not work when the account-based pairing method is enabled in the Google Messages app. Unlink other devices and switch back to the QR code method to continue using the bridge.") + go user.sendMarkdownBridgeAlert(true, "Switched to Google account pairing, please switch back or relogin with `login-google`.") } else { - go user.sendMarkdownBridgeAlert(false, "Switched back to QR pairing, bridge should work now") + go user.sendMarkdownBridgeAlert(false, "Switched back to QR pairing, bridge should be reconnected") // Assume connection is ready now even if it wasn't before user.ready = true } @@ -874,7 +955,7 @@ func (user *User) FillBridgeState(state status.BridgeState) status.BridgeState { func (user *User) Logout(state status.BridgeState, unpair bool) (logoutOK bool) { if user.Client != nil && unpair { - _, err := user.Client.Unpair() + err := user.Client.Unpair() if err != nil { user.zlog.Debug().Err(err).Msg("Error sending unpair request") } else {