serverpackets.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. package remoteauth
  2. import (
  3. "crypto/sha256"
  4. "encoding/base64"
  5. "encoding/json"
  6. "fmt"
  7. "time"
  8. "github.com/gorilla/websocket"
  9. )
  10. type serverPacket interface {
  11. process(client *Client) error
  12. }
  13. func (c *Client) processMessages() {
  14. type rawPacket struct {
  15. OP string `json:"op"`
  16. }
  17. defer c.close()
  18. for {
  19. c.Lock()
  20. _, packet, err := c.conn.ReadMessage()
  21. c.Unlock()
  22. if err != nil {
  23. if websocket.IsUnexpectedCloseError(err, websocket.CloseNormalClosure) {
  24. c.Lock()
  25. c.err = err
  26. c.Unlock()
  27. }
  28. return
  29. }
  30. raw := rawPacket{}
  31. if err := json.Unmarshal(packet, &raw); err != nil {
  32. c.Lock()
  33. c.err = err
  34. c.Unlock()
  35. return
  36. }
  37. var dest interface{}
  38. switch raw.OP {
  39. case "hello":
  40. dest = new(serverHello)
  41. case "nonce_proof":
  42. dest = new(serverNonceProof)
  43. case "pending_remote_init":
  44. dest = new(serverPendingRemoteInit)
  45. case "pending_finish":
  46. dest = new(serverPendingFinish)
  47. case "finish":
  48. dest = new(serverFinish)
  49. case "cancel":
  50. dest = new(serverCancel)
  51. case "heartbeat_ack":
  52. dest = new(serverHeartbeatAck)
  53. }
  54. if err := json.Unmarshal(packet, dest); err != nil {
  55. c.Lock()
  56. c.err = err
  57. c.Unlock()
  58. return
  59. }
  60. op := dest.(serverPacket)
  61. err = op.process(c)
  62. if err != nil {
  63. c.Lock()
  64. c.err = err
  65. c.Unlock()
  66. return
  67. }
  68. }
  69. }
  70. // /////////////////////////////////////////////////////////////////////////////
  71. // Hello
  72. // /////////////////////////////////////////////////////////////////////////////
  73. type serverHello struct {
  74. Timeout int `json:"timeout_ms"`
  75. HeartbeatInterval int `json:"heartbeat_interval"`
  76. }
  77. func (h *serverHello) process(client *Client) error {
  78. // Create our heartbeat handler
  79. ticker := time.NewTicker(time.Duration(h.HeartbeatInterval) * time.Millisecond)
  80. go func() {
  81. defer ticker.Stop()
  82. for {
  83. select {
  84. // case <-client.ctx.Done():
  85. // return
  86. case <-ticker.C:
  87. h := clientHeartbeat{}
  88. if err := h.send(client); err != nil {
  89. client.Lock()
  90. client.err = err
  91. client.Unlock()
  92. return
  93. }
  94. }
  95. }
  96. }()
  97. go func() {
  98. duration := time.Duration(h.Timeout) * time.Millisecond
  99. <-time.After(duration)
  100. client.Lock()
  101. client.err = fmt.Errorf("Timed out after %s", duration)
  102. client.close()
  103. client.Unlock()
  104. }()
  105. i := clientInit{}
  106. return i.send(client)
  107. }
  108. // /////////////////////////////////////////////////////////////////////////////
  109. // NonceProof
  110. // /////////////////////////////////////////////////////////////////////////////
  111. type serverNonceProof struct {
  112. EncryptedNonce string `json:"encrypted_nonce"`
  113. }
  114. func (n *serverNonceProof) process(client *Client) error {
  115. plaintext, err := client.decrypt(n.EncryptedNonce)
  116. if err != nil {
  117. return err
  118. }
  119. rawProof := sha256.Sum256(plaintext)
  120. // The [:] syntax is to return an unsized slice as the sum function returns
  121. // one.
  122. proof := base64.RawURLEncoding.EncodeToString(rawProof[:])
  123. c := clientNonceProof{Proof: proof}
  124. return c.send(client)
  125. }
  126. // /////////////////////////////////////////////////////////////////////////////
  127. // HeartbeatAck
  128. // /////////////////////////////////////////////////////////////////////////////
  129. type serverHeartbeatAck struct{}
  130. func (h *serverHeartbeatAck) process(client *Client) error {
  131. client.heartbeats -= 1
  132. return nil
  133. }
  134. // /////////////////////////////////////////////////////////////////////////////
  135. // PendingRemoteInit
  136. // /////////////////////////////////////////////////////////////////////////////
  137. type serverPendingRemoteInit struct {
  138. Fingerprint string `json:"fingerprint"`
  139. }
  140. func (p *serverPendingRemoteInit) process(client *Client) error {
  141. url := "https://discordapp.com/ra/" + p.Fingerprint
  142. client.qrChan <- url
  143. close(client.qrChan)
  144. return nil
  145. }
  146. // /////////////////////////////////////////////////////////////////////////////
  147. // PendingFinish
  148. // /////////////////////////////////////////////////////////////////////////////
  149. type serverPendingFinish struct {
  150. EncryptedUserPayload string `json:"encrypted_user_payload"`
  151. }
  152. func (p *serverPendingFinish) process(client *Client) error {
  153. plaintext, err := client.decrypt(p.EncryptedUserPayload)
  154. if err != nil {
  155. return err
  156. }
  157. return client.user.update(string(plaintext))
  158. }
  159. // /////////////////////////////////////////////////////////////////////////////
  160. // Finish
  161. // /////////////////////////////////////////////////////////////////////////////
  162. type serverFinish struct {
  163. EncryptedToken string `json:"encrypted_token"`
  164. }
  165. func (f *serverFinish) process(client *Client) error {
  166. plaintext, err := client.decrypt(f.EncryptedToken)
  167. if err != nil {
  168. return err
  169. }
  170. client.user.Token = string(plaintext)
  171. client.close()
  172. return nil
  173. }
  174. // /////////////////////////////////////////////////////////////////////////////
  175. // Cancel
  176. // /////////////////////////////////////////////////////////////////////////////
  177. type serverCancel struct{}
  178. func (c *serverCancel) process(client *Client) error {
  179. client.close()
  180. return nil
  181. }