auth_test.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. package handler
  2. import (
  3. "testing"
  4. "github.com/google/uuid"
  5. "github.com/mkaminski/goaim/oscar"
  6. "github.com/mkaminski/goaim/server"
  7. "github.com/mkaminski/goaim/state"
  8. "github.com/stretchr/testify/assert"
  9. "github.com/stretchr/testify/mock"
  10. )
  11. func TestReceiveAndSendBUCPLoginRequest(t *testing.T) {
  12. userGoodPwd := state.User{
  13. ScreenName: "sn_user_a",
  14. AuthKey: "auth_key_user",
  15. }
  16. assert.NoError(t, userGoodPwd.HashPassword("good_pwd"))
  17. userBadPwd := userGoodPwd
  18. assert.NoError(t, userBadPwd.HashPassword("bad_pwd"))
  19. cases := []struct {
  20. name string
  21. cfg server.Config
  22. userInDB state.User
  23. sessionUUID uuid.UUID
  24. inputSNAC oscar.SNAC_0x17_0x02_BUCPLoginRequest
  25. // expectOutput is the SNAC payload sent from the server to the
  26. // recipient client
  27. expectOutput oscar.XMessage
  28. }{
  29. {
  30. name: "login with valid password, expect OK login response",
  31. cfg: server.Config{
  32. OSCARHost: "127.0.0.1",
  33. BOSPort: 1234,
  34. },
  35. userInDB: userGoodPwd,
  36. sessionUUID: uuid.UUID{1, 2, 3},
  37. inputSNAC: oscar.SNAC_0x17_0x02_BUCPLoginRequest{
  38. TLVRestBlock: oscar.TLVRestBlock{
  39. TLVList: oscar.TLVList{
  40. oscar.NewTLV(oscar.TLVPasswordHash, userGoodPwd.PassHash),
  41. oscar.NewTLV(oscar.TLVScreenName, userGoodPwd.ScreenName),
  42. },
  43. },
  44. },
  45. expectOutput: oscar.XMessage{
  46. SnacFrame: oscar.SnacFrame{
  47. FoodGroup: oscar.BUCP,
  48. SubGroup: oscar.BUCPLoginResponse,
  49. },
  50. SnacOut: oscar.SNAC_0x17_0x03_BUCPLoginResponse{
  51. TLVRestBlock: oscar.TLVRestBlock{
  52. TLVList: oscar.TLVList{
  53. oscar.NewTLV(oscar.TLVScreenName, userGoodPwd.ScreenName),
  54. oscar.NewTLV(oscar.TLVReconnectHere, "127.0.0.1:1234"),
  55. oscar.NewTLV(oscar.TLVAuthorizationCookie, uuid.UUID{1, 2, 3}.String()),
  56. },
  57. },
  58. },
  59. },
  60. },
  61. {
  62. name: "login with bad password, expect OK login response (Cfg.DisableAuth=true)",
  63. cfg: server.Config{
  64. OSCARHost: "127.0.0.1",
  65. BOSPort: 1234,
  66. DisableAuth: true,
  67. },
  68. userInDB: userGoodPwd,
  69. sessionUUID: uuid.UUID{1, 2, 3},
  70. inputSNAC: oscar.SNAC_0x17_0x02_BUCPLoginRequest{
  71. TLVRestBlock: oscar.TLVRestBlock{
  72. TLVList: oscar.TLVList{
  73. oscar.NewTLV(oscar.TLVPasswordHash, userBadPwd.PassHash),
  74. oscar.NewTLV(oscar.TLVScreenName, userBadPwd.ScreenName),
  75. },
  76. },
  77. },
  78. expectOutput: oscar.XMessage{
  79. SnacFrame: oscar.SnacFrame{
  80. FoodGroup: oscar.BUCP,
  81. SubGroup: oscar.BUCPLoginResponse,
  82. },
  83. SnacOut: oscar.SNAC_0x17_0x03_BUCPLoginResponse{
  84. TLVRestBlock: oscar.TLVRestBlock{
  85. TLVList: oscar.TLVList{
  86. oscar.NewTLV(oscar.TLVScreenName, userBadPwd.ScreenName),
  87. oscar.NewTLV(oscar.TLVReconnectHere, "127.0.0.1:1234"),
  88. oscar.NewTLV(oscar.TLVAuthorizationCookie, uuid.UUID{1, 2, 3}.String()),
  89. },
  90. },
  91. },
  92. },
  93. },
  94. {
  95. name: "login with bad password, expect failed login response (Cfg.DisableAuth=false)",
  96. cfg: server.Config{
  97. OSCARHost: "127.0.0.1",
  98. BOSPort: 1234,
  99. },
  100. userInDB: userGoodPwd,
  101. sessionUUID: uuid.UUID{1, 2, 3},
  102. inputSNAC: oscar.SNAC_0x17_0x02_BUCPLoginRequest{
  103. TLVRestBlock: oscar.TLVRestBlock{
  104. TLVList: oscar.TLVList{
  105. oscar.NewTLV(oscar.TLVPasswordHash, userBadPwd.PassHash),
  106. oscar.NewTLV(oscar.TLVScreenName, userBadPwd.ScreenName),
  107. },
  108. },
  109. },
  110. expectOutput: oscar.XMessage{
  111. SnacFrame: oscar.SnacFrame{
  112. FoodGroup: oscar.BUCP,
  113. SubGroup: oscar.BUCPLoginResponse,
  114. },
  115. SnacOut: oscar.SNAC_0x17_0x03_BUCPLoginResponse{
  116. TLVRestBlock: oscar.TLVRestBlock{
  117. TLVList: oscar.TLVList{
  118. oscar.NewTLV(oscar.TLVScreenName, userBadPwd.ScreenName),
  119. oscar.NewTLV(oscar.TLVErrorSubcode, uint16(0x01)),
  120. },
  121. },
  122. },
  123. },
  124. },
  125. }
  126. for _, tc := range cases {
  127. t.Run(tc.name, func(t *testing.T) {
  128. sess := newTestSession(tc.userInDB.ScreenName, sessOptID(tc.sessionUUID.String()))
  129. um := newMockUserManager(t)
  130. um.EXPECT().
  131. GetUser(tc.userInDB.ScreenName).
  132. Return(&userGoodPwd, nil).
  133. Maybe()
  134. um.EXPECT().
  135. UpsertUser(mock.Anything).
  136. Return(nil).
  137. Maybe()
  138. sm := newMockSessionManager(t)
  139. sm.EXPECT().
  140. NewSessionWithSN(tc.sessionUUID.String(), tc.userInDB.ScreenName).
  141. Return(sess).
  142. Maybe()
  143. svc := AuthService{
  144. config: tc.cfg,
  145. sessionManager: sm,
  146. userManager: um,
  147. }
  148. fnNewUUID := func() uuid.UUID {
  149. return tc.sessionUUID
  150. }
  151. outputSNAC, err := svc.ReceiveAndSendBUCPLoginRequest(tc.inputSNAC, fnNewUUID)
  152. assert.NoError(t, err)
  153. assert.Equal(t, tc.expectOutput, outputSNAC)
  154. })
  155. }
  156. }
  157. func TestReceiveAndSendAuthChallenge(t *testing.T) {
  158. cases := []struct {
  159. name string
  160. cfg server.Config
  161. userInDB *state.User
  162. fnNewUUID uuid.UUID
  163. inputSNAC oscar.SNAC_0x17_0x06_BUCPChallengeRequest
  164. expectOutput oscar.XMessage
  165. }{
  166. {
  167. name: "login with valid username, expect OK login response",
  168. cfg: server.Config{
  169. OSCARHost: "127.0.0.1",
  170. BOSPort: 1234,
  171. },
  172. userInDB: &state.User{
  173. ScreenName: "sn_user_a",
  174. AuthKey: "auth_key_user_a",
  175. },
  176. fnNewUUID: uuid.UUID{1, 2, 3},
  177. inputSNAC: oscar.SNAC_0x17_0x06_BUCPChallengeRequest{
  178. TLVRestBlock: oscar.TLVRestBlock{
  179. TLVList: oscar.TLVList{
  180. oscar.NewTLV(oscar.TLVScreenName, "sn_user_a"),
  181. },
  182. },
  183. },
  184. expectOutput: oscar.XMessage{
  185. SnacFrame: oscar.SnacFrame{
  186. FoodGroup: oscar.BUCP,
  187. SubGroup: oscar.BUCPChallengeResponse,
  188. },
  189. SnacOut: oscar.SNAC_0x17_0x07_BUCPChallengeResponse{
  190. AuthKey: "auth_key_user_a",
  191. },
  192. },
  193. },
  194. {
  195. name: "login with invalid username, expect OK login response (Cfg.DisableAuth=true)",
  196. cfg: server.Config{
  197. OSCARHost: "127.0.0.1",
  198. BOSPort: 1234,
  199. DisableAuth: true,
  200. },
  201. userInDB: nil,
  202. fnNewUUID: uuid.UUID{1, 2, 3},
  203. inputSNAC: oscar.SNAC_0x17_0x06_BUCPChallengeRequest{
  204. TLVRestBlock: oscar.TLVRestBlock{
  205. TLVList: oscar.TLVList{
  206. oscar.NewTLV(oscar.TLVScreenName, "sn_user_b"),
  207. },
  208. },
  209. },
  210. expectOutput: oscar.XMessage{
  211. SnacFrame: oscar.SnacFrame{
  212. FoodGroup: oscar.BUCP,
  213. SubGroup: oscar.BUCPChallengeResponse,
  214. },
  215. SnacOut: oscar.SNAC_0x17_0x07_BUCPChallengeResponse{
  216. AuthKey: uuid.UUID{1, 2, 3}.String(),
  217. },
  218. },
  219. },
  220. {
  221. name: "login with invalid username, expect failed login response (Cfg.DisableAuth=false)",
  222. cfg: server.Config{
  223. OSCARHost: "127.0.0.1",
  224. BOSPort: 1234,
  225. },
  226. userInDB: nil,
  227. fnNewUUID: uuid.UUID{1, 2, 3},
  228. inputSNAC: oscar.SNAC_0x17_0x06_BUCPChallengeRequest{
  229. TLVRestBlock: oscar.TLVRestBlock{
  230. TLVList: oscar.TLVList{
  231. oscar.NewTLV(oscar.TLVScreenName, "sn_user_b"),
  232. },
  233. },
  234. },
  235. expectOutput: oscar.XMessage{
  236. SnacFrame: oscar.SnacFrame{
  237. FoodGroup: oscar.BUCP,
  238. SubGroup: oscar.BUCPLoginResponse,
  239. },
  240. SnacOut: oscar.SNAC_0x17_0x03_BUCPLoginResponse{
  241. TLVRestBlock: oscar.TLVRestBlock{
  242. TLVList: oscar.TLVList{
  243. oscar.NewTLV(oscar.TLVErrorSubcode, uint16(0x01)),
  244. },
  245. },
  246. },
  247. },
  248. },
  249. }
  250. for _, tc := range cases {
  251. t.Run(tc.name, func(t *testing.T) {
  252. um := newMockUserManager(t)
  253. um.EXPECT().
  254. GetUser(string(tc.inputSNAC.TLVList[0].Val)).
  255. Return(tc.userInDB, nil).
  256. Maybe()
  257. svc := AuthService{
  258. config: tc.cfg,
  259. userManager: um,
  260. }
  261. fnNewUUID := func() uuid.UUID {
  262. return tc.fnNewUUID
  263. }
  264. outputSNAC, err := svc.ReceiveAndSendAuthChallenge(tc.inputSNAC, fnNewUUID)
  265. assert.NoError(t, err)
  266. assert.Equal(t, tc.expectOutput, outputSNAC)
  267. })
  268. }
  269. }