provider_test.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. package ike
  2. import (
  3. "bytes"
  4. "context"
  5. "errors"
  6. "io"
  7. "net"
  8. "testing"
  9. "time"
  10. "vocat/internal/vowifi"
  11. )
  12. var errFirstAuthObserved = errors.New("test: first IKE_AUTH observed")
  13. type constantReader struct{ value byte }
  14. func (reader constantReader) Read(destination []byte) (int, error) {
  15. for index := range destination {
  16. destination[index] = reader.value
  17. }
  18. return len(destination), nil
  19. }
  20. type firstAuthCaptureTransport struct {
  21. t *testing.T
  22. calls int
  23. suite negotiatedSuite
  24. keys ikeKeys
  25. spii [8]byte
  26. spir [8]byte
  27. nonceI []byte
  28. nonceR []byte
  29. floated bool
  30. }
  31. func (transport *firstAuthCaptureTransport) LocalAddr() *net.UDPAddr {
  32. return &net.UDPAddr{IP: net.IPv4(192, 0, 2, 10), Port: 500}
  33. }
  34. func (transport *firstAuthCaptureTransport) RemoteAddr() *net.UDPAddr {
  35. return &net.UDPAddr{IP: net.IPv4(198, 51, 100, 20), Port: 500}
  36. }
  37. func (transport *firstAuthCaptureTransport) Float(context.Context) error {
  38. transport.floated = true
  39. return nil
  40. }
  41. func (transport *firstAuthCaptureTransport) RoundTrip(_ context.Context, packet []byte) ([]byte, error) {
  42. transport.calls++
  43. switch transport.calls {
  44. case 1:
  45. return transport.answerIKEInit(packet)
  46. case 2:
  47. return nil, transport.observeFirstAuth(packet)
  48. default:
  49. return nil, errors.New("test: unexpected exchange")
  50. }
  51. }
  52. func (transport *firstAuthCaptureTransport) answerIKEInit(packet []byte) ([]byte, error) {
  53. header, body, err := parseIKEPacket(packet)
  54. if err != nil {
  55. return nil, err
  56. }
  57. payloads, err := parsePayloadChain(header.NextPayload, body)
  58. if err != nil {
  59. return nil, err
  60. }
  61. ke, err := onePayload(payloads, payloadKE)
  62. if err != nil {
  63. return nil, err
  64. }
  65. nonce, err := onePayload(payloads, payloadNonce)
  66. if err != nil {
  67. return nil, err
  68. }
  69. group := uint16(ke.Body[0])<<8 | uint16(ke.Body[1])
  70. if group != dhMODP1024 || len(ke.Body[4:]) != 128 {
  71. transport.t.Fatalf("Vodafone init KE = group %d length %d", group, len(ke.Body[4:]))
  72. }
  73. serverDH, err := newDHExchange(group, constantReader{value: 0x77})
  74. if err != nil {
  75. return nil, err
  76. }
  77. shared, err := serverDH.shared(ke.Body[4:])
  78. if err != nil {
  79. return nil, err
  80. }
  81. transport.suite = legacyTestSuite()
  82. transport.spii = header.InitiatorSPI
  83. transport.spir = [8]byte{0x80, 1, 2, 3, 4, 5, 6, 7}
  84. transport.nonceI = append([]byte(nil), nonce.Body...)
  85. transport.nonceR = bytes.Repeat([]byte{0x88}, 32)
  86. transport.keys, err = deriveIKEKeys(
  87. transport.suite,
  88. shared,
  89. transport.nonceI,
  90. transport.nonceR,
  91. transport.spii,
  92. transport.spir,
  93. )
  94. if err != nil {
  95. return nil, err
  96. }
  97. selectedSA, _ := marshalProposals([]proposal{{
  98. Number: 1,
  99. Protocol: protocolIKE,
  100. Transforms: []transform{
  101. {Type: transformEncryption, ID: encryptionAESCBC, KeyLength: 128},
  102. {Type: transformPRF, ID: prfHMACSHA1},
  103. {Type: transformIntegrity, ID: integrityHMACSHA1_96},
  104. {Type: transformDH, ID: dhMODP1024},
  105. },
  106. }})
  107. keBody := make([]byte, 4+len(serverDH.Public))
  108. keBody[1] = byte(group)
  109. copy(keBody[4:], serverDH.Public)
  110. first, responseBody, _ := marshalPayloadChain([]payload{
  111. {Type: payloadSA, Body: selectedSA},
  112. {Type: payloadKE, Body: keBody},
  113. {Type: payloadNonce, Body: transport.nonceR},
  114. })
  115. return ikeHeader{
  116. InitiatorSPI: transport.spii,
  117. ResponderSPI: transport.spir,
  118. NextPayload: first,
  119. Exchange: exchangeIKEInit,
  120. Flags: flagResponse,
  121. }.marshal(responseBody), nil
  122. }
  123. func (transport *firstAuthCaptureTransport) observeFirstAuth(packet []byte) error {
  124. header, payloads, err := decryptPayloads(
  125. packet,
  126. transport.suite,
  127. transport.keys.SKei,
  128. transport.keys.SKai,
  129. )
  130. if err != nil {
  131. return err
  132. }
  133. if header.Exchange != exchangeIKEAuth || header.MessageID != 1 || header.Flags != flagInitiator {
  134. transport.t.Fatalf("first IKE_AUTH header = %#v", header)
  135. }
  136. idr, err := onePayload(payloads, payloadIDr)
  137. if err != nil {
  138. transport.t.Fatal(err)
  139. }
  140. if idr.Body[0] != 2 || string(idr.Body[4:]) != "ims" {
  141. transport.t.Fatalf("requested IDr = type %d value %q", idr.Body[0], idr.Body[4:])
  142. }
  143. foundEAPOnly := false
  144. for _, item := range payloadsOfType(payloads, payloadNotify) {
  145. kind, data, err := parseNotify(item)
  146. if err != nil {
  147. transport.t.Fatal(err)
  148. }
  149. if kind == notifyEAPOnlyAuth && len(data) == 0 {
  150. foundEAPOnly = true
  151. }
  152. }
  153. if !foundEAPOnly {
  154. transport.t.Fatal("first IKE_AUTH omitted EAP_ONLY_AUTHENTICATION")
  155. }
  156. for _, kind := range []uint8{payloadIDi, payloadSA, payloadTSi, payloadTSr, payloadCP} {
  157. if _, err := onePayload(payloads, kind); err != nil {
  158. transport.t.Fatalf("first IKE_AUTH payload %d: %v", kind, err)
  159. }
  160. }
  161. return errFirstAuthObserved
  162. }
  163. func (*firstAuthCaptureTransport) SendESP(context.Context, []byte) error {
  164. return errors.New("test: unused")
  165. }
  166. func (*firstAuthCaptureTransport) ReceiveESP(context.Context, []byte) (int, error) {
  167. return 0, errors.New("test: unused")
  168. }
  169. func (*firstAuthCaptureTransport) SendSessionPacket(context.Context, []byte, bool) error {
  170. return errors.New("test: unused")
  171. }
  172. func (*firstAuthCaptureTransport) ReceiveSessionPacket(context.Context, []byte) (int, bool, error) {
  173. return 0, false, errors.New("test: unused")
  174. }
  175. func (*firstAuthCaptureTransport) Close() error { return nil }
  176. type unusedInstaller struct{}
  177. func (unusedInstaller) Install(context.Context, ChildSAConfig) (ChildSAHandle, error) {
  178. return nil, errors.New("test: installer must not run")
  179. }
  180. func TestProviderVodafoneFirstAuthIsEAPOnlyAndRequestsIMSAPN(t *testing.T) {
  181. capture := &firstAuthCaptureTransport{t: t}
  182. provider, err := NewProvider(Config{
  183. Random: constantReader{value: 0x42},
  184. Timeout: time.Second,
  185. Installer: unusedInstaller{},
  186. APN: "ims",
  187. })
  188. if err != nil {
  189. t.Fatal(err)
  190. }
  191. provider.transportFactory = func(
  192. context.Context,
  193. transportConfig,
  194. vowifi.ProxyRoute,
  195. string,
  196. ) (datagramTransport, error) {
  197. return capture, nil
  198. }
  199. aka := &testAKAProvider{}
  200. _, err = provider.Start(context.Background(), vowifi.TunnelRequest{
  201. DeviceID: "ec20-1",
  202. Identity: vowifi.SIMIdentity{
  203. ICCID: "8944100000000000000",
  204. IMSI: "234150123456789",
  205. HomeMCC: "234",
  206. HomeMNC: "15",
  207. },
  208. EPDG: "epdg.epc.mnc015.mcc234.pub.3gppnetwork.org",
  209. AKA: aka,
  210. })
  211. if !errors.Is(err, errFirstAuthObserved) {
  212. t.Fatalf("Start() error = %v, want capture sentinel", err)
  213. }
  214. if capture.calls != 2 || capture.floated || aka.calls != 0 {
  215. t.Fatalf("capture calls=%d floated=%v AKA calls=%d", capture.calls, capture.floated, aka.calls)
  216. }
  217. }
  218. var _ io.Reader = constantReader{}
  219. var _ datagramTransport = (*firstAuthCaptureTransport)(nil)