Add support for unpairing google logins

This commit is contained in:
Tulir Asokan 2024-02-23 16:32:12 +02:00
parent ca15922d7c
commit 49a3fd983f
8 changed files with 294 additions and 207 deletions

View file

@ -35,6 +35,8 @@ type AuthData struct {
WebEncryptionKey []byte `json:"web_encryption_key,omitempty"` WebEncryptionKey []byte `json:"web_encryption_key,omitempty"`
SessionID uuid.UUID `json:"session_id,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"` Cookies map[string]string `json:"cookies,omitempty"`
} }

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -84,7 +84,7 @@ message SignInGaiaResponse {
} }
message GaiaPairingRequestContainer { message GaiaPairingRequestContainer {
string pairingUUID = 1; string pairingAttemptID = 1;
BrowserDetails browserDetails = 2; BrowserDetails browserDetails = 2;
int64 startTimestamp = 3; int64 startTimestamp = 3;
bytes data = 4; bytes data = 4;
@ -98,6 +98,10 @@ message GaiaPairingResponseContainer {
bytes data = 5; bytes data = 5;
} }
message RevokeGaiaPairingRequest {
string pairingAttemptID = 1;
}
message RPCGaiaData { message RPCGaiaData {
message UnknownContainer { message UnknownContainer {
message Item2 { message Item2 {

View file

@ -54,7 +54,6 @@ func main() {
} }
_ = file.Close() _ = file.Close()
cli = libgm.NewClient(&sess, log) cli = libgm.NewClient(&sess, log)
log.Info().Str("device_id", sess.SessionID.String()).Msg("meow")
cli.SetEventHandler(evtHandler) cli.SetEventHandler(evtHandler)
if doLogin { if doLogin {
err = cli.DoGaiaPairing(func(emoji string) { err = cli.DoGaiaPairing(func(emoji string) {

View file

@ -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 { if c.AuthData.TachyonAuthToken == nil || c.AuthData.Browser == nil {
return nil, nil return nil, nil
} }
@ -150,3 +150,12 @@ func (c *Client) Unpair() (*gmproto.RevokeRelayPairingResponse, error) {
c.makeProtobufHTTPRequest(util.RevokeRelayPairingURL, payload, ContentTypeProtobuf), 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
}

View file

@ -267,6 +267,7 @@ func (c *Client) DoGaiaPairing(emojiCallback func(string)) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to parse destination UUID: %w", err) return fmt.Errorf("failed to parse destination UUID: %w", err)
} }
c.AuthData.DestRegID = destRegUUID
go c.doLongPoll(false) go c.doLongPoll(false)
ps := NewPairingSession(destRegUUID) ps := NewPairingSession(destRegUUID)
clientInit, clientFinish, err := ps.PreparePayloads() clientInit, clientFinish, err := ps.PreparePayloads()
@ -297,6 +298,7 @@ func (c *Client) DoGaiaPairing(emojiCallback func(string)) error {
} }
c.AuthData.RequestCrypto.AESKey = doHKDF(ps.NextKey, encryptionKeyInfo, []byte("client")) c.AuthData.RequestCrypto.AESKey = doHKDF(ps.NextKey, encryptionKeyInfo, []byte("client"))
c.AuthData.RequestCrypto.HMACKey = doHKDF(ps.NextKey, encryptionKeyInfo, []byte("server")) c.AuthData.RequestCrypto.HMACKey = doHKDF(ps.NextKey, encryptionKeyInfo, []byte("server"))
c.AuthData.PairingID = ps.UUID
c.triggerEvent(&events.PairSuccessful{}) c.triggerEvent(&events.PairSuccessful{})
go func() { go func() {
@ -316,10 +318,10 @@ func (c *Client) sendGaiaPairingMessage(sess PairingSession, action gmproto.Acti
resp, err := c.sessionHandler.sendMessageWithParams(SendMessageParams{ resp, err := c.sessionHandler.sendMessageWithParams(SendMessageParams{
Action: action, Action: action,
Data: &gmproto.GaiaPairingRequestContainer{ Data: &gmproto.GaiaPairingRequestContainer{
PairingUUID: sess.UUID.String(), PairingAttemptID: sess.UUID.String(),
BrowserDetails: util.BrowserDetailsMessage, BrowserDetails: util.BrowserDetailsMessage,
StartTimestamp: sess.Start.UnixMilli(), StartTimestamp: sess.Start.UnixMilli(),
Data: msg, Data: msg,
}, },
DontEncrypt: true, DontEncrypt: true,
CustomTTL: (300 * time.Second).Microseconds(), CustomTTL: (300 * time.Second).Microseconds(),
@ -338,3 +340,14 @@ func (c *Client) sendGaiaPairingMessage(sess PairingSession, action gmproto.Acti
} }
return &respDat, nil 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(),
},
DestRegistrationIDs: []string{c.AuthData.DestRegID.String()},
NoPingOnTimeout: true,
})
}

View file

@ -948,7 +948,7 @@ func (user *User) FillBridgeState(state status.BridgeState) status.BridgeState {
func (user *User) Logout(state status.BridgeState, unpair bool) (logoutOK bool) { func (user *User) Logout(state status.BridgeState, unpair bool) (logoutOK bool) {
if user.Client != nil && unpair { if user.Client != nil && unpair {
_, err := user.Client.Unpair() err := user.Client.Unpair()
if err != nil { if err != nil {
user.zlog.Debug().Err(err).Msg("Error sending unpair request") user.zlog.Debug().Err(err).Msg("Error sending unpair request")
} else { } else {