mobile-subscriber 0.0.1.alpha5 → 0.0.1.beta1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|