mobile-subscriber 0.0.1.alpha5 → 0.0.1.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +13 -1
- data/lib/mobile-subscriber.rb +2 -0
- data/lib/mobile_subscriber/detection/from_msisdn_http_request_header.rb +58 -125
- data/lib/mobile_subscriber/detection/from_x_nokia_msisdn_http_request_header.rb +27 -42
- data/lib/mobile_subscriber/detection/from_x_up_calling_line_id_http_request_header.rb +52 -87
- data/lib/mobile_subscriber/detection/from_x_up_ch_msisdn_http_request_header.rb +28 -39
- data/lib/mobile_subscriber/detection/from_x_up_subno_http_request_header.rb +28 -41
- data/lib/mobile_subscriber/detection/from_x_wap_sesiones3g_mdn_http_request_header.rb +39 -0
- data/lib/mobile_subscriber/detection/http_request_info.rb +75 -0
- data/lib/mobile_subscriber/isdn.rb +18 -16
- data/lib/mobile_subscriber/version.rb +1 -1
- data/spec/detection/from_msisdn_http_request_header_spec.rb +7 -3
- data/spec/detection/from_x_nokia_msisdn_http_request_header_spec.rb +6 -2
- data/spec/detection/from_x_up_calling_line_id_http_request_header_spec.rb +6 -2
- data/spec/detection/from_x_wap_sesiones3g_mdn_http_request_header_spec.rb +29 -0
- data/spec/factories/requests.rb +9 -0
- data/spec/models/isdn_spec.rb +4 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b57bb989e630712c7b4a06d051a7038006b426c1
|
4
|
+
data.tar.gz: 00d70b45ea77d7e0ebeae56c47c3fb19960c5ebc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df5e3a68907f3c6a33350a16be66e20ed2d385d133ee2547e1848613ae179a5231c8a145ccf4ed46ae1a2f41c785c2c816c612c4c62a50381ba4140a8b4fface
|
7
|
+
data.tar.gz: 2e4a5f0151692218c8cf90d20de3288f31aa91ebaba3533dbb67607176272acc940caee34ca243c617af9697c70168aeccd5f0438cd8eb5a54e267d0ae392989
|
data/README.md
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
# MobileSubscriber Gem
|
2
2
|
|
3
|
-
|
3
|
+
It's a fact that the Mobile network providers (carriers, operators & such) share
|
4
|
+
subscriber identity data to approved 3rd parties when users navigate via Web to
|
5
|
+
the 3rd parties' websites.
|
6
|
+
|
7
|
+
The problem is that generally the algorythms used by these 3rd parties offer
|
8
|
+
no security against forged HTTP requests.
|
9
|
+
|
10
|
+
The goals of this project are basically to detect the user's identity for the
|
11
|
+
3rd parties, in the most secure and reliably as possible:
|
12
|
+
- Validate the mobile user's identity by checking the originating IP address
|
13
|
+
- Validate the request hopping between relaying proxies
|
4
14
|
|
5
15
|
## Installation
|
6
16
|
|
@@ -34,3 +44,5 @@ TODO: Write usage instructions here
|
|
34
44
|
## References
|
35
45
|
- [MSISDN - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/MSISDN)
|
36
46
|
- [Mobile country code - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/Mobile_country_code)
|
47
|
+
- [Mobile networks: exploiting HTTP headers and data traffic - DefCamp 2012](http://www.slideshare.net/DefCamp/mobile-networks-exploiting-http-headers-and-data-traffic)
|
48
|
+
- [Privacy Leaks in Mobile Phone Internet Access - Collin Mulliner](http://www.mulliner.org/collin/academic/publications/mobile_web_privacy_icin10_mulliner.pdf)
|
data/lib/mobile-subscriber.rb
CHANGED
@@ -1,137 +1,70 @@
|
|
1
1
|
require 'mobile_subscriber/dictionaries/dialing_and_country_codes'
|
2
2
|
|
3
|
-
module MobileSubscriber
|
4
|
-
module Detection
|
3
|
+
module MobileSubscriber::Detection
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
5
|
+
# Módulo que provee métodos de detección y validacion para MSISDN por el
|
6
|
+
# header de HTTP 'Msisdn':
|
7
|
+
# - Claro Brasil
|
8
|
+
# - Claro Chile
|
9
|
+
# - Claro Colombia
|
10
|
+
# - Claro Costa Rica
|
11
|
+
# - Claro República Dominicana
|
12
|
+
# - Claro Ecuador
|
13
|
+
# - Claro El Salvador
|
14
|
+
# - Claro Guatemala
|
15
|
+
# - Claro Nicaragua
|
16
|
+
# - Claro Panamá
|
17
|
+
# - Claro Paraguay
|
18
|
+
module FromMsisdnHttpRequestHeader
|
20
19
|
|
21
|
-
|
20
|
+
def extract_from_msisdn_http_request_header(http_request_info)
|
21
|
+
if msisdn = http_request_info.headers['Msisdn'] and msisdn.length >= 8
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
country_code = (
|
24
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] ||
|
25
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
|
26
|
+
)
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
when 'CO'
|
58
|
-
# Claro Colombia
|
59
|
-
{
|
60
|
-
id: msisdn,
|
61
|
-
mobile_country_code: "732",
|
62
|
-
mobile_network_code: "101"
|
63
|
-
}.merge(detection_cues: detection_cues)
|
64
|
-
when 'CR'
|
65
|
-
# Claro Costa Rica
|
66
|
-
{
|
67
|
-
id: msisdn,
|
68
|
-
mobile_country_code: "712",
|
69
|
-
mobile_network_code: "03"
|
70
|
-
}.merge(detection_cues: detection_cues)
|
71
|
-
when 'DO'
|
72
|
-
# Claro Dominicana:
|
73
|
-
{
|
74
|
-
id: msisdn,
|
75
|
-
mobile_country_code: "370",
|
76
|
-
mobile_network_code: "02"
|
77
|
-
}.merge(detection_cues: detection_cues)
|
78
|
-
when 'EC'
|
79
|
-
# Claro Ecuador:
|
80
|
-
{
|
81
|
-
id: msisdn,
|
82
|
-
mobile_country_code: "740",
|
83
|
-
mobile_network_code: "01"
|
84
|
-
}.merge(detection_cues: detection_cues)
|
85
|
-
when 'SV'
|
86
|
-
# Claro El Salvador:
|
87
|
-
{
|
88
|
-
id: msisdn,
|
89
|
-
mobile_country_code: "706",
|
90
|
-
mobile_network_code: "01"
|
91
|
-
}.merge(detection_cues: detection_cues)
|
92
|
-
when 'GT'
|
93
|
-
# Claro Guatemala:
|
94
|
-
{
|
95
|
-
id: msisdn,
|
96
|
-
mobile_country_code: "704",
|
97
|
-
mobile_network_code: "01"
|
98
|
-
}.merge(detection_cues: detection_cues)
|
99
|
-
when 'HN'
|
100
|
-
# Claro Honduras:
|
101
|
-
{
|
102
|
-
id: msisdn,
|
103
|
-
mobile_country_code: "708",
|
104
|
-
mobile_network_code: "001"
|
105
|
-
}.merge(detection_cues: detection_cues)
|
106
|
-
when 'NI'
|
107
|
-
# Claro Nicaragua:
|
108
|
-
{
|
109
|
-
id: msisdn,
|
110
|
-
mobile_country_code: "710",
|
111
|
-
mobile_network_code: "21"
|
112
|
-
}.merge(detection_cues: detection_cues)
|
113
|
-
when 'PA'
|
114
|
-
# Claro Panamá:
|
115
|
-
{
|
116
|
-
id: msisdn,
|
117
|
-
mobile_country_code: "714",
|
118
|
-
mobile_network_code: "03"
|
119
|
-
}.merge(detection_cues: detection_cues)
|
120
|
-
when 'PY'
|
121
|
-
# Claro Paraguay:
|
122
|
-
{
|
123
|
-
id: msisdn,
|
124
|
-
mobile_country_code: "744",
|
125
|
-
mobile_network_code: "02"
|
126
|
-
}.merge(detection_cues: detection_cues)
|
127
|
-
end
|
128
|
-
|
129
|
-
end
|
28
|
+
# Determine the Network Operator (MCC + MNC tuple):
|
29
|
+
# TODO: Validate IP ranges, additional headers, etc.
|
30
|
+
network_id_tuple = case country_code
|
31
|
+
when 'BR' # Claro Brasil
|
32
|
+
# TODO: Determine (if possible) the MNC (05, 38)
|
33
|
+
{ mcc: "724", mnc: "05" }
|
34
|
+
when 'CL' # Claro Chile
|
35
|
+
{ mcc: "730", mnc: "03" }
|
36
|
+
when 'CO' # Claro Colombia
|
37
|
+
{ mcc: "732", mnc: "101" }
|
38
|
+
when 'CR' # Claro Costa Rica
|
39
|
+
{ mcc: "712", mnc: "03" }
|
40
|
+
when 'DO' # Claro Dominicana:
|
41
|
+
{ mcc: "370", mnc: "02" }
|
42
|
+
when 'EC' # Claro Ecuador:
|
43
|
+
{ mcc: "740", mnc: "01" }
|
44
|
+
when 'SV' # Claro El Salvador:
|
45
|
+
{ mcc: "706", mnc: "01" }
|
46
|
+
when 'GT' # Claro Guatemala:
|
47
|
+
{ mcc: "704", mnc: "01" }
|
48
|
+
when 'HN' # Claro Honduras:
|
49
|
+
{ mcc: "708", mnc: "001" }
|
50
|
+
when 'NI' # Claro Nicaragua:
|
51
|
+
{ mcc: "710", mnc: "21" }
|
52
|
+
when 'PA' # Claro Panamá:
|
53
|
+
{ mcc: "714", mnc: "03" }
|
54
|
+
when 'PY' # Claro Paraguay:
|
55
|
+
{ mcc: "744", mnc: "02" }
|
56
|
+
end
|
130
57
|
|
131
|
-
|
58
|
+
# Return only if we identified the network:
|
59
|
+
if network_id_tuple.present?
|
60
|
+
{
|
61
|
+
id: msisdn,
|
62
|
+
mobile_country_code: network_id_tuple[:mcc],
|
63
|
+
mobile_network_code: network_id_tuple[:mnc],
|
64
|
+
http_request_info: http_request_info
|
65
|
+
}
|
132
66
|
end
|
133
67
|
end
|
134
|
-
|
135
68
|
end
|
136
69
|
end
|
137
70
|
end
|
@@ -1,53 +1,38 @@
|
|
1
1
|
require 'mobile_subscriber/dictionaries/dialing_and_country_codes'
|
2
|
-
module MobileSubscriber
|
3
|
-
module Detection
|
2
|
+
module MobileSubscriber::Detection
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
# Módulo que provee métodos de deteccion y validacion para MSISDN's de:
|
5
|
+
# - Telcel México
|
6
|
+
# - Claro Argentina
|
7
|
+
module FromXNokiaMsisdnHttpRequestHeader
|
9
8
|
|
10
|
-
|
9
|
+
def extract_from_x_nokia_msisdn_http_request_header(http_request_info)
|
10
|
+
if msisdn = http_request_info.headers['X-Nokia-Msisdn'] and msisdn.length >= 8
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
country_code = (
|
13
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] ||
|
14
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
|
15
|
+
)
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
+
# Determine the Network Operator tuple (MCC + MNC):
|
18
|
+
# TODO: Validate IP ranges, additional headers, etc.
|
19
|
+
network_id_tuple = case country_code
|
20
|
+
when 'MX' # Telcel México:
|
21
|
+
{ mcc: "334", mnc: "020" }
|
17
22
|
|
18
|
-
|
19
|
-
|
20
|
-
detection_cues = {
|
21
|
-
remote_ip: request.env["REMOTE_ADDR"],
|
22
|
-
http_request_headers: { 'X-Nokia-Msisdn' => msisdn }
|
23
|
-
}
|
24
|
-
|
25
|
-
country_code = MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] || MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
|
26
|
-
|
27
|
-
# Determinar la procedencia del MSISDN
|
28
|
-
# TODO: Validar por IP, etc.
|
29
|
-
case country_code
|
30
|
-
when 'MX'
|
31
|
-
# Telcel México:
|
32
|
-
{
|
33
|
-
id: msisdn,
|
34
|
-
mobile_country_code: "334",
|
35
|
-
mobile_network_code: "020"
|
36
|
-
}.merge(detection_cues: detection_cues)
|
37
|
-
|
38
|
-
# Claro Argentina:
|
39
|
-
when 'AR'
|
40
|
-
{
|
41
|
-
id: msisdn,
|
42
|
-
mobile_country_code: "722",
|
43
|
-
mobile_network_code: "330"
|
44
|
-
}.merge(detection_cues: detection_cues)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
isdn_attributes
|
23
|
+
when 'AR' # Claro Argentina:
|
24
|
+
{ mcc: "722", mnc: "330" }
|
49
25
|
end
|
50
26
|
|
27
|
+
# Return only if we identified the network:
|
28
|
+
if network_id_tuple.present?
|
29
|
+
{
|
30
|
+
id: msisdn,
|
31
|
+
mobile_country_code: network_id_tuple[:mcc],
|
32
|
+
mobile_network_code: network_id_tuple[:mnc],
|
33
|
+
http_request_info: http_request_info
|
34
|
+
}
|
35
|
+
end
|
51
36
|
end
|
52
37
|
end
|
53
38
|
end
|
@@ -1,100 +1,65 @@
|
|
1
1
|
require 'mobile_subscriber/dictionaries/dialing_and_country_codes'
|
2
|
-
module MobileSubscriber
|
3
|
-
module Detection
|
2
|
+
module MobileSubscriber::Detection
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
4
|
+
# Módulo que provee métodos de deteccion y validacion para MSISDN por el
|
5
|
+
# header de HTTP 'X-Up-Calling-Line-Id':
|
6
|
+
# - Claro Perú
|
7
|
+
# - TIM (Telecom Italia Mobile) Brasil
|
8
|
+
# - OI Brasil
|
9
|
+
# - Movistar México
|
10
|
+
# - Movistar Argentina
|
11
|
+
# - Movistar Ecuador
|
12
|
+
# - Movistar Perú
|
13
|
+
module FromXUpCallingLineIdHttpRequestHeader
|
15
14
|
|
16
|
-
|
15
|
+
def extract_from_x_up_calling_line_id_http_request_header(http_request_info)
|
16
|
+
if msisdn = http_request_info.headers['X-Up-Calling-Line-Id'] and msisdn.length >= 8
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
country_code = (
|
19
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] ||
|
20
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
|
21
|
+
)
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
else
|
43
|
-
# Is a Movistar Peru subscriber:
|
44
|
-
{
|
45
|
-
id: msisdn,
|
46
|
-
mobile_country_code: "716",
|
47
|
-
mobile_network_code: "06"
|
48
|
-
}.merge(detection_cues: detection_cues)
|
49
|
-
end
|
50
|
-
when 'BR'
|
51
|
-
if http_request_x_msp_apn_header = request.env["HTTP_X_MSP_APN"] and http_request_x_msp_apn_header.present?
|
52
|
-
detection_cues[:http_request_headers]['X-Msp-Apn'] = http_request_x_msp_apn_header
|
53
|
-
if http_request_x_msp_apn_header =~ /OI/i
|
54
|
-
# Is a Oi Brazil subscriber:
|
55
|
-
{
|
56
|
-
id: msisdn,
|
57
|
-
mobile_country_code: "724",
|
58
|
-
mobile_network_code: "30"
|
59
|
-
}.merge(detection_cues: detection_cues)
|
60
|
-
else
|
61
|
-
# Is a TIM Brasil subscriber:
|
62
|
-
{
|
63
|
-
id: msisdn,
|
64
|
-
mobile_country_code: "724",
|
65
|
-
mobile_network_code: "02"
|
66
|
-
}.merge(detection_cues: detection_cues)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
when 'MX'
|
70
|
-
# Is a Movistar Mexico subscriber:
|
71
|
-
{
|
72
|
-
id: msisdn,
|
73
|
-
mobile_country_code: "334",
|
74
|
-
mobile_network_code: "030"
|
75
|
-
}.merge(detection_cues: detection_cues)
|
76
|
-
when 'AR'
|
77
|
-
# Is a Movistar Argentina subscriber:
|
78
|
-
# TODO: Detect if MNC is 010 or 070 (Different MHz Bands)
|
79
|
-
{
|
80
|
-
id: msisdn,
|
81
|
-
mobile_country_code: "722",
|
82
|
-
mobile_network_code: "010"
|
83
|
-
}.merge(detection_cues: detection_cues)
|
84
|
-
when 'EC'
|
85
|
-
# Is a Movistar Ecuador subscriber:
|
86
|
-
{
|
87
|
-
id: msisdn,
|
88
|
-
mobile_country_code: "740",
|
89
|
-
mobile_network_code: "00"
|
90
|
-
}.merge(detection_cues: detection_cues)
|
23
|
+
# Determine the Network Operator tuple (MCC + MNC):
|
24
|
+
# TODO: Validate IP ranges, additional headers, etc.
|
25
|
+
network_id_tuple = case country_code
|
26
|
+
when 'PE'
|
27
|
+
if (via_header = http_request_info.headers['Via']).present? and via_header =~ /Comverse/i
|
28
|
+
# Claro Peru:
|
29
|
+
{ mcc: "716", mnc: "10" }
|
30
|
+
else
|
31
|
+
# Movistar Peru:
|
32
|
+
{ mcc: "716", mnc: "06" }
|
33
|
+
end
|
34
|
+
when 'BR'
|
35
|
+
if x_msp_apn_header = request.env["X-Msp-Apn"] and x_msp_apn_header.present?
|
36
|
+
if http_request_x_msp_apn_header =~ /OI/i
|
37
|
+
# Oi Brazil:
|
38
|
+
{ mcc: "724", mnc: "30" }
|
39
|
+
else
|
40
|
+
# TIM Brazil:
|
41
|
+
{ mcc: "724", mnc: "02" }
|
91
42
|
end
|
92
43
|
end
|
44
|
+
when 'MX' # Movistar Mexico:
|
45
|
+
{ mcc: "334", mnc: "030" }
|
46
|
+
when 'AR' # Movistar Argentina:
|
47
|
+
# TODO: Determine (if possible) the MNC (010 or 070)
|
48
|
+
{ mcc: "722", mnc: "010" }
|
49
|
+
when 'EC' # Movistar Ecuador:
|
50
|
+
{ mcc: "740", mnc: "00" }
|
51
|
+
end
|
93
52
|
|
94
|
-
|
53
|
+
# Return only if we identified the network:
|
54
|
+
if network_id_tuple.present?
|
55
|
+
{
|
56
|
+
id: msisdn,
|
57
|
+
mobile_country_code: network_id_tuple[:mcc],
|
58
|
+
mobile_network_code: network_id_tuple[:mnc],
|
59
|
+
http_request_info: http_request_info
|
60
|
+
}
|
95
61
|
end
|
96
62
|
end
|
97
|
-
|
98
63
|
end
|
99
64
|
end
|
100
65
|
end
|
@@ -1,46 +1,35 @@
|
|
1
1
|
require 'mobile_subscriber/dictionaries/dialing_and_country_codes'
|
2
|
-
module MobileSubscriber
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
}
|
22
|
-
|
23
|
-
country_code = MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] || MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
|
24
|
-
|
25
|
-
# Determinar la procedencia del MSISDN
|
26
|
-
# TODO: Validar por IP, etc.
|
27
|
-
case country_code
|
28
|
-
when 'BR'
|
29
|
-
# Vivo:
|
30
|
-
# TODO: Determinar el MNC correcto (06, 10, 11, 23)
|
31
|
-
{
|
32
|
-
id: msisdn,
|
33
|
-
mobile_country_code: "724",
|
34
|
-
mobile_network_code: "06"
|
35
|
-
}.merge(detection_cues: detection_cues)
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
isdn_attributes
|
2
|
+
module MobileSubscriber::Detection
|
3
|
+
# Módulo que provee métodos de deteccion y validacion para MSISDN's de:
|
4
|
+
# - Vivo Brasil
|
5
|
+
module FromXUpChMsisdnHttpRequestHeader
|
6
|
+
|
7
|
+
def extract_from_x_up_ch_msisdn_http_request_header(http_request_info)
|
8
|
+
if msisdn = http_request_info.headers['X-Up-Ch-Msisdn'] and msisdn.length >= 8
|
9
|
+
|
10
|
+
country_code = (
|
11
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] ||
|
12
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
|
13
|
+
)
|
14
|
+
|
15
|
+
# Determine the Network Operator tuple (MCC + MNC):
|
16
|
+
# TODO: Validate IP ranges, additional headers, etc.
|
17
|
+
network_id_tuple = case country_code
|
18
|
+
when 'BR' # Vivo Brazil:
|
19
|
+
# TODO: Determine (if possible) the MNC (06, 10, 11, 23)
|
20
|
+
{ mcc: "724", mnc: "06" }
|
40
21
|
end
|
41
22
|
|
23
|
+
# Return only if we identified the network:
|
24
|
+
if network_id_tuple.present?
|
25
|
+
{
|
26
|
+
id: msisdn,
|
27
|
+
mobile_country_code: network_id_tuple[:mcc],
|
28
|
+
mobile_network_code: network_id_tuple[:mnc],
|
29
|
+
http_request_info: http_request_info
|
30
|
+
}
|
31
|
+
end
|
42
32
|
end
|
43
|
-
|
44
33
|
end
|
45
34
|
end
|
46
35
|
end
|
@@ -1,48 +1,35 @@
|
|
1
1
|
require 'mobile_subscriber/dictionaries/dialing_and_country_codes'
|
2
|
-
module MobileSubscriber
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
remote_ip: request.env["REMOTE_ADDR"],
|
23
|
-
http_request_headers: { header_name => msisdn }
|
24
|
-
}
|
25
|
-
|
26
|
-
country_code = MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] || MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
|
27
|
-
|
28
|
-
# Determinar la procedencia del MSISDN
|
29
|
-
# TODO: Validar por IP, etc.
|
30
|
-
case country_code
|
31
|
-
when 'CO'
|
32
|
-
# Comcel Colombia
|
33
|
-
{
|
34
|
-
id: msisdn,
|
35
|
-
mobile_country_code: "732",
|
36
|
-
mobile_network_code: "101"
|
37
|
-
}.merge(detection_cues: detection_cues)
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
2
|
+
module MobileSubscriber::Detection
|
3
|
+
# Módulo que provee métodos de deteccion y validacion para MSISDN por el
|
4
|
+
# header de HTTP 'Msisdn':
|
5
|
+
# - Comcel Colombia
|
6
|
+
module FromXUpSubnoHttpRequestHeader
|
7
|
+
|
8
|
+
def extract_from_x_up_subno_http_request_header(http_request_info)
|
9
|
+
if msisdn = http_request_info.headers['X-Up-Subno'] and msisdn.length >= 8
|
10
|
+
|
11
|
+
country_code = (
|
12
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] ||
|
13
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
|
14
|
+
)
|
15
|
+
|
16
|
+
# Determine the Network Operator tuple (MCC + MNC):
|
17
|
+
# TODO: Validate IP ranges, additional headers, etc.
|
18
|
+
network_id_tuple = case country_code
|
19
|
+
when 'CO' # Comcel Colombia
|
20
|
+
{ mcc: "732", mnc: "101" }
|
21
|
+
end
|
41
22
|
|
42
|
-
|
23
|
+
# Return only if we identified the network:
|
24
|
+
if network_id_tuple.present?
|
25
|
+
{
|
26
|
+
id: msisdn,
|
27
|
+
mobile_country_code: network_id_tuple[:mcc],
|
28
|
+
mobile_network_code: network_id_tuple[:mnc],
|
29
|
+
http_request_info: http_request_info
|
30
|
+
}
|
43
31
|
end
|
44
32
|
end
|
45
|
-
|
46
33
|
end
|
47
34
|
end
|
48
35
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'mobile_subscriber/dictionaries/dialing_and_country_codes'
|
2
|
+
|
3
|
+
module MobileSubscriber::Detection
|
4
|
+
# Módulo que provee métodos de detección y validacion para MSISDN por el
|
5
|
+
# header de HTTP 'X-Wap-Sesiones3g-Mdn':
|
6
|
+
# - Iusacell
|
7
|
+
module FromXWapSesiones3gMdnHttpRequestHeader
|
8
|
+
|
9
|
+
def extract_from_x_wap_sesiones3g_mdn_http_request_header(http_request_info)
|
10
|
+
if msisdn = http_request_info.headers['X-Wap-Sesiones3g-Mdn'] and msisdn.length >= 8
|
11
|
+
|
12
|
+
country_code = (
|
13
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] ||
|
14
|
+
MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
|
15
|
+
)
|
16
|
+
|
17
|
+
# Determine the Network Operator tuple (MCC + MNC):
|
18
|
+
# TODO: Validate IP ranges, additional headers, etc.
|
19
|
+
network_id_tuple = case country_code
|
20
|
+
when 'MX' # Iusacell Mexico:
|
21
|
+
# TODO: Determine (if possible) the MNC:
|
22
|
+
# - MNC "040": Iusacell/Unefon
|
23
|
+
# - MNC "050": Iusacell
|
24
|
+
{ mcc: "334", mnc: "040" }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return only if we identified the network:
|
28
|
+
if network_id_tuple.present?
|
29
|
+
{
|
30
|
+
id: msisdn,
|
31
|
+
mobile_country_code: network_id_tuple[:mcc],
|
32
|
+
mobile_network_code: network_id_tuple[:mnc],
|
33
|
+
http_request_info: http_request_info
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module MobileSubscriber::Detection
|
2
|
+
class HttpRequestInfo
|
3
|
+
attr_reader :remote_ip, :headers
|
4
|
+
|
5
|
+
def initialize(env)
|
6
|
+
|
7
|
+
@remote_ip = env['REMOTE_ADDR']
|
8
|
+
|
9
|
+
# Reference Links:
|
10
|
+
# - http://www.slideshare.net/DefCamp/mobile-networks-exploiting-http-headers-and-data-traffic
|
11
|
+
# - http://www.mulliner.org/collin/academic/publications/mobile_web_privacy_icin10_mulliner.pdf
|
12
|
+
@headers = [
|
13
|
+
# HTTP Headers that contain important request details for validation
|
14
|
+
'Max-Forwards', # Para validar el número de forwards que el cliente permite... muy pobre..
|
15
|
+
'Via',
|
16
|
+
'X-Forwarded-For', # lista de IP's que originaron la petición, en caso de pasar por proxies:
|
17
|
+
|
18
|
+
# HTTP headers that contain the MSISDN:
|
19
|
+
# http://www.mulliner.org/collin/academic/publications/mobile_web_privacy_icin10_mulliner.pdf
|
20
|
+
'Cookie',
|
21
|
+
'Igcli',
|
22
|
+
'Msisdn',
|
23
|
+
'Rapmin',
|
24
|
+
'X-Fh-Msisdn',
|
25
|
+
"X-H3-G-Msisdn",
|
26
|
+
'X-Hts-Clid',
|
27
|
+
'X-Jinny-Cid',
|
28
|
+
'X-Msisdn',
|
29
|
+
'X-Msp-Clid',
|
30
|
+
'X-Msp-Msisdn',
|
31
|
+
'X-Network-Info',
|
32
|
+
'X-Nokia-Msisdn',
|
33
|
+
'X-Nx-Clid',
|
34
|
+
'X-Orange-Cli',
|
35
|
+
'X-Up-Calling-Line',
|
36
|
+
'X-Up-Calling-Line-Id', # Not in referenced literature
|
37
|
+
'X-Up-Ch-Msisdn', # Not in referenced literature
|
38
|
+
'X-Up-Lsid',
|
39
|
+
'X-Up-Subno', # Not in referenced literature
|
40
|
+
'X-Wap-Fh-Subscriber-Info',
|
41
|
+
'X-Wap-Msisdn',
|
42
|
+
'X-Wap-Sesiones3g-Mdn', # Not in referenced literature
|
43
|
+
'X-Wsb-Cli',
|
44
|
+
|
45
|
+
# Headers that contain bearer information:
|
46
|
+
# http://www.mulliner.org/collin/academic/publications/mobile_web_privacy_icin10_mulliner.pdf
|
47
|
+
'Bearer',
|
48
|
+
'Bearer-Indication',
|
49
|
+
'New-Bearer-Header',
|
50
|
+
'Nokia-Bearer',
|
51
|
+
'X-Nokia-Bearer',
|
52
|
+
'X-Nokia-Musicshop-Bearer',
|
53
|
+
'X-Up-Bear-Type', # NOT A TYPO
|
54
|
+
'X-Up-Bearer-Type',
|
55
|
+
'X-Bearer-Type',
|
56
|
+
|
57
|
+
# Headers that contain roaming information:
|
58
|
+
# http://www.mulliner.org/collin/academic/publications/mobile_web_privacy_icin10_mulliner.pdf
|
59
|
+
'X-Orange-Roaming',
|
60
|
+
'X-Nokia-Roaming',
|
61
|
+
'X-Roaming',
|
62
|
+
'X-Sdp-Roaming'
|
63
|
+
].inject({}.with_indifferent_access) do |collected_headers, header_name|
|
64
|
+
header_env_key = "HTTP_#{header_name.gsub('-','_').upcase}"
|
65
|
+
|
66
|
+
if env.has_key? header_env_key
|
67
|
+
collected_headers[header_name] = env[header_env_key].strip
|
68
|
+
end
|
69
|
+
|
70
|
+
collected_headers
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -6,20 +6,20 @@ module MobileSubscriber
|
|
6
6
|
|
7
7
|
class ISDN
|
8
8
|
|
9
|
-
attr_reader :id, :mobile_country_code, :mobile_network_code, :
|
9
|
+
attr_reader :id, :mobile_country_code, :mobile_network_code, :http_request_info
|
10
10
|
alias_method :to_s, :id
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
extend MobileSubscriber::Detection::FromMsisdnHttpRequestHeader
|
13
|
+
extend MobileSubscriber::Detection::FromXNokiaMsisdnHttpRequestHeader
|
14
|
+
extend MobileSubscriber::Detection::FromXUpCallingLineIdHttpRequestHeader
|
15
|
+
extend MobileSubscriber::Detection::FromXUpChMsisdnHttpRequestHeader
|
16
|
+
extend MobileSubscriber::Detection::FromXUpSubnoHttpRequestHeader
|
17
17
|
|
18
18
|
def initialize(attributes={})
|
19
19
|
@id = attributes.delete :id
|
20
20
|
@mobile_country_code = attributes.delete :mobile_country_code
|
21
21
|
@mobile_network_code = attributes.delete :mobile_network_code
|
22
|
-
@
|
22
|
+
@http_request_info = attributes.delete :http_request_info
|
23
23
|
end
|
24
24
|
|
25
25
|
def dialing_code
|
@@ -47,8 +47,6 @@ module MobileSubscriber
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
|
51
|
-
|
52
50
|
def inspect
|
53
51
|
"<MobileSubscriber::ISDN #{self.id} (#{self.http_validated? ? '' : 'not '}validated by HTTP)>"
|
54
52
|
end
|
@@ -59,15 +57,19 @@ module MobileSubscriber
|
|
59
57
|
|
60
58
|
# Creates a new MobileSubscriber::ISDN from a Rack::Request object
|
61
59
|
def self.new_from_request(request)
|
62
|
-
|
60
|
+
http_request_info = Detection::HttpRequestInfo.new request.env
|
61
|
+
|
62
|
+
detection_results = self.methods.select do |x|
|
63
63
|
x.to_s =~ /\Aextract_from_(\w+)_http_request_header\z/i
|
64
|
-
end.
|
65
|
-
|
66
|
-
|
67
|
-
|
64
|
+
end.map do |detection_method|
|
65
|
+
self.send detection_method, http_request_info
|
66
|
+
end.compact
|
67
|
+
|
68
|
+
# TODO: Select first from a preference order:
|
69
|
+
detection = detection_results.first if detection_results.any?
|
68
70
|
|
69
|
-
if
|
70
|
-
validated_isdn = new(
|
71
|
+
if detection.present?
|
72
|
+
validated_isdn = new(detection)
|
71
73
|
validated_isdn.send :http_validated!
|
72
74
|
validated_isdn
|
73
75
|
end
|
@@ -2,16 +2,20 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe MobileSubscriber::Detection::FromMsisdnHttpRequestHeader do
|
4
4
|
|
5
|
-
include described_class
|
5
|
+
include described_class
|
6
6
|
|
7
7
|
let :test_request do
|
8
8
|
build :mobile_request_from_claro_brasil
|
9
9
|
end
|
10
10
|
|
11
|
+
let :test_request_info do
|
12
|
+
MobileSubscriber::Detection::HttpRequestInfo.new test_request.env
|
13
|
+
end
|
14
|
+
|
11
15
|
describe "the returned object of self.extract_from_msisdn_http_request_header" do
|
12
16
|
|
13
17
|
subject do
|
14
|
-
extract_from_msisdn_http_request_header
|
18
|
+
extract_from_msisdn_http_request_header test_request_info
|
15
19
|
end
|
16
20
|
|
17
21
|
context "when given a request made from Claro Brasil" do
|
@@ -53,7 +57,7 @@ describe MobileSubscriber::Detection::FromMsisdnHttpRequestHeader do
|
|
53
57
|
expect(subject[:mobile_network_code]).to eq '01'
|
54
58
|
end
|
55
59
|
end
|
56
|
-
|
60
|
+
|
57
61
|
end
|
58
62
|
|
59
63
|
end
|
@@ -2,12 +2,16 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe MobileSubscriber::Detection::FromXNokiaMsisdnHttpRequestHeader do
|
4
4
|
|
5
|
-
include described_class
|
5
|
+
include described_class
|
6
|
+
|
7
|
+
let :test_request_info do
|
8
|
+
MobileSubscriber::Detection::HttpRequestInfo.new test_request.env
|
9
|
+
end
|
6
10
|
|
7
11
|
describe "the returned object of self.extract_from_msisdn_http_request_header" do
|
8
12
|
|
9
13
|
subject do
|
10
|
-
extract_from_x_nokia_msisdn_http_request_header
|
14
|
+
extract_from_x_nokia_msisdn_http_request_header test_request_info
|
11
15
|
end
|
12
16
|
|
13
17
|
context "when given a request made from Telcel México" do
|
@@ -2,12 +2,16 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe MobileSubscriber::Detection::FromXUpCallingLineIdHttpRequestHeader do
|
4
4
|
|
5
|
-
include described_class
|
5
|
+
include described_class
|
6
|
+
|
7
|
+
let :test_request_info do
|
8
|
+
MobileSubscriber::Detection::HttpRequestInfo.new test_request.env
|
9
|
+
end
|
6
10
|
|
7
11
|
describe "the returned object of self.extract_from_msisdn_http_request_header" do
|
8
12
|
|
9
13
|
subject do
|
10
|
-
extract_from_x_up_calling_line_id_http_request_header
|
14
|
+
extract_from_x_up_calling_line_id_http_request_header test_request_info
|
11
15
|
end
|
12
16
|
|
13
17
|
context "when given a request made from Claro Perú" do
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe MobileSubscriber::Detection::FromXWapSesiones3gMdnHttpRequestHeader, focus: true do
|
4
|
+
|
5
|
+
include described_class
|
6
|
+
|
7
|
+
let :test_request_info do
|
8
|
+
MobileSubscriber::Detection::HttpRequestInfo.new test_request.env
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "the returned object of self.extract_from_msisdn_http_request_header" do
|
12
|
+
|
13
|
+
subject do
|
14
|
+
extract_from_x_wap_sesiones3g_mdn_http_request_header test_request_info
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when given a request made from Iusacell Mexico" do
|
18
|
+
let(:test_request) { build :mobile_request_from_iusacell_mexico }
|
19
|
+
|
20
|
+
include_examples "of detection of msisdn from a valid mexican mobile network http request"
|
21
|
+
|
22
|
+
it "has a :mobile_network_code value of '040' or '050'" do
|
23
|
+
expect(subject[:mobile_network_code]).to match /040|050/i
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/spec/factories/requests.rb
CHANGED
@@ -25,6 +25,15 @@ FactoryGirl.define do
|
|
25
25
|
)
|
26
26
|
end
|
27
27
|
|
28
|
+
factory :mobile_request_from_iusacell_mexico do
|
29
|
+
initialize_with do
|
30
|
+
new build(:common_mobile_request_env).merge(
|
31
|
+
"REMOTE_ADDR" => "201.144.162.4",
|
32
|
+
"HTTP_X_WAP_SESIONES3G_MDN" => "528110000000"
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
28
37
|
factory :mobile_request_from_telcel_mexico do
|
29
38
|
initialize_with do
|
30
39
|
new build(:common_mobile_request_env).merge(
|
data/spec/models/isdn_spec.rb
CHANGED
@@ -38,6 +38,10 @@ describe MobileSubscriber::ISDN do
|
|
38
38
|
expect(subject).to respond_to :http_validated?
|
39
39
|
end
|
40
40
|
|
41
|
+
it "responds to #http_request_info" do
|
42
|
+
expect(subject).to respond_to :http_request_info
|
43
|
+
end
|
44
|
+
|
41
45
|
describe "detection from request headers" do
|
42
46
|
|
43
47
|
shared_examples "of detection from a valid request" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mobile-subscriber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1.
|
4
|
+
version: 0.0.1.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roberto Quintanilla
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -118,6 +118,8 @@ files:
|
|
118
118
|
- lib/mobile_subscriber/detection/from_x_up_calling_line_id_http_request_header.rb
|
119
119
|
- lib/mobile_subscriber/detection/from_x_up_ch_msisdn_http_request_header.rb
|
120
120
|
- lib/mobile_subscriber/detection/from_x_up_subno_http_request_header.rb
|
121
|
+
- lib/mobile_subscriber/detection/from_x_wap_sesiones3g_mdn_http_request_header.rb
|
122
|
+
- lib/mobile_subscriber/detection/http_request_info.rb
|
121
123
|
- lib/mobile_subscriber/dictionaries/dialing_and_country_codes.rb
|
122
124
|
- lib/mobile_subscriber/dictionaries/mobile_and_iso_country_codes.rb
|
123
125
|
- lib/mobile_subscriber/dictionaries/operator_data.rb
|
@@ -128,6 +130,7 @@ files:
|
|
128
130
|
- spec/detection/from_msisdn_http_request_header_spec.rb
|
129
131
|
- spec/detection/from_x_nokia_msisdn_http_request_header_spec.rb
|
130
132
|
- spec/detection/from_x_up_calling_line_id_http_request_header_spec.rb
|
133
|
+
- spec/detection/from_x_wap_sesiones3g_mdn_http_request_header_spec.rb
|
131
134
|
- spec/factories/requests.rb
|
132
135
|
- spec/mobile_subscriber_spec.rb
|
133
136
|
- spec/models/isdn_spec.rb
|
@@ -163,6 +166,7 @@ test_files:
|
|
163
166
|
- spec/detection/from_msisdn_http_request_header_spec.rb
|
164
167
|
- spec/detection/from_x_nokia_msisdn_http_request_header_spec.rb
|
165
168
|
- spec/detection/from_x_up_calling_line_id_http_request_header_spec.rb
|
169
|
+
- spec/detection/from_x_wap_sesiones3g_mdn_http_request_header_spec.rb
|
166
170
|
- spec/factories/requests.rb
|
167
171
|
- spec/mobile_subscriber_spec.rb
|
168
172
|
- spec/models/isdn_spec.rb
|