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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0f3d86284c8cd6a42a0fdab25eba82cb6c1ba05b
4
- data.tar.gz: fbcf9b5f54072d1a6f9580da21bc6afbd4314d51
3
+ metadata.gz: b57bb989e630712c7b4a06d051a7038006b426c1
4
+ data.tar.gz: 00d70b45ea77d7e0ebeae56c47c3fb19960c5ebc
5
5
  SHA512:
6
- metadata.gz: 0acdb66c244b26c2360958eeaf0a392b3786d59e73946348e5abfc1f249ea47e978576711b76e3a2f4a960c60e1ad4ca546e879c085a2821be8223c8ad2317ab
7
- data.tar.gz: d7f91b0655d285b3f9ce75993ee7702088b35e17887590c77cd54df922703fd421000a49e08ddf6d1dc45b9e6c3d630039c8b0652048d4f0a60a527e60b98a7c
6
+ metadata.gz: df5e3a68907f3c6a33350a16be66e20ed2d385d133ee2547e1848613ae179a5231c8a145ccf4ed46ae1a2f41c785c2c816c612c4c62a50381ba4140a8b4fface
7
+ data.tar.gz: 2e4a5f0151692218c8cf90d20de3288f31aa91ebaba3533dbb67607176272acc940caee34ca243c617af9697c70168aeccd5f0438cd8eb5a54e267d0ae392989
data/README.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # MobileSubscriber Gem
2
2
 
3
- TODO: Write a gem description
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)
@@ -13,5 +13,7 @@ module MobileSubscriber
13
13
  autoload :FromXUpCallingLineIdHttpRequestHeader
14
14
  autoload :FromXUpChMsisdnHttpRequestHeader
15
15
  autoload :FromXUpSubnoHttpRequestHeader
16
+ autoload :FromXWapSesiones3gMdnHttpRequestHeader
17
+ autoload :HttpRequestInfo
16
18
  end
17
19
  end
@@ -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
- # Módulo que provee métodos de detección y validacion para MSISDN por el
7
- # header de HTTP 'Msisdn':
8
- # - Claro Brasil
9
- # - Claro Chile
10
- # - Claro Colombia
11
- # - Claro Costa Rica
12
- # - Claro República Dominicana
13
- # - Claro Ecuador
14
- # - Claro El Salvador
15
- # - Claro Guatemala
16
- # - Claro Nicaragua
17
- # - Claro Panamá
18
- # - Claro Paraguay
19
- module FromMsisdnHttpRequestHeader
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
- extend ActiveSupport::Concern
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
- module ClassMethods
24
- def extract_from_msisdn_http_request_header(request)
25
- header_name = 'Msisdn'
26
- header_env_key = "HTTP_#{header_name.gsub('-','_').upcase}"
23
+ country_code = (
24
+ MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] ||
25
+ MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
26
+ )
27
27
 
28
- isdn_attributes = nil
29
-
30
- isdn_attributes = if msisdn = request.env[header_env_key] and msisdn.strip.length >= 8
31
- msisdn.strip!
32
- detection_cues = {
33
- remote_ip: request.env["REMOTE_ADDR"],
34
- http_request_headers: { 'Msisdn' => msisdn }
35
- }
36
-
37
- country_code = MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] || MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
38
-
39
- # Determinar la procedencia del MSISDN
40
- # TODO: Validar por IP, etc.
41
- case country_code
42
- when 'BR'
43
- # Claro Brasil
44
- # TODO: Determinar correctamente el MNC (05, 38)
45
- {
46
- id: msisdn,
47
- mobile_country_code: "724",
48
- mobile_network_code: "05"
49
- }.merge(detection_cues: detection_cues)
50
- when 'CL'
51
- # Claro Chile
52
- {
53
- id: msisdn,
54
- mobile_country_code: "730",
55
- mobile_network_code: "03"
56
- }.merge(detection_cues: detection_cues)
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
- isdn_attributes
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
- # Módulo que provee métodos de deteccion y validacion para MSISDN's de:
6
- # - Telcel México
7
- # - Claro Argentina
8
- module FromXNokiaMsisdnHttpRequestHeader
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
- extend ActiveSupport::Concern
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
- module ClassMethods
13
- def extract_from_x_nokia_msisdn_http_request_header(request)
12
+ country_code = (
13
+ MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] ||
14
+ MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
15
+ )
14
16
 
15
- header_name = 'X-Nokia-Msisdn'
16
- header_env_key = "HTTP_#{header_name.gsub('-','_').upcase}"
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
- isdn_attributes = if msisdn = request.env[header_env_key] and msisdn.strip.length >= 8
19
- msisdn.strip!
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
- # Módulo que provee métodos de deteccion y validacion para MSISDN por el
6
- # header de HTTP 'X-Up-Calling-Line-Id':
7
- # - Claro Perú
8
- # - TIM (Telecom Italia Mobile) Brasil
9
- # - OI Brasil
10
- # - Movistar México
11
- # - Movistar Argentina
12
- # - Movistar Ecuador
13
- # - Movistar Perú
14
- module FromXUpCallingLineIdHttpRequestHeader
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
- extend ActiveSupport::Concern
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
- module ClassMethods
19
- def extract_from_x_up_calling_line_id_http_request_header(request)
20
- header_name = 'X-Up-Calling-Line-Id'
21
- header_env_key = "HTTP_#{header_name.gsub('-','_').upcase}"
18
+ country_code = (
19
+ MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] ||
20
+ MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
21
+ )
22
22
 
23
- isdn_attributes = if msisdn = request.env[header_env_key] and msisdn.strip.length >= 8
24
- msisdn.strip!
25
- detection_cues = {
26
- remote_ip: request.env["REMOTE_ADDR"],
27
- http_request_headers: { header_name => msisdn }
28
- }
29
-
30
- country_code = MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,2]] || MobileSubscriber::DIALING_COUNTRY_CODES[msisdn[0,3]]
31
-
32
- case country_code
33
- when 'PE'
34
- if (http_request_via_header = request.env["HTTP_VIA"]).present? and http_request_via_header =~ /Comverse/i
35
- # Is Claro Peru subscriber:
36
- detection_cues[:http_request_headers]['Via'] = http_request_via_header
37
- {
38
- id: msisdn,
39
- mobile_country_code: "716",
40
- mobile_network_code: "10"
41
- }.merge(detection_cues: detection_cues)
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
- isdn_attributes
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
- module Detection
4
-
5
- # Módulo que provee métodos de deteccion y validacion para MSISDN's de:
6
- # - Vivo Brasil
7
- module FromXUpChMsisdnHttpRequestHeader
8
-
9
- extend ActiveSupport::Concern
10
-
11
- module ClassMethods
12
- def extract_from_x_up_ch_msisdn_http_request_header(request)
13
- header_name = 'X-Up-Ch-Msisdn'
14
- header_env_key = "HTTP_#{header_name.gsub('-','_').upcase}"
15
-
16
- isdn_attributes = if msisdn = request.env[header_env_key] and msisdn.strip.length >= 8
17
- msisdn.strip!
18
- detection_cues = {
19
- remote_ip: request.env["REMOTE_ADDR"],
20
- http_request_headers: { 'X-Up-Ch-Msisdn' => msisdn }
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
- module Detection
4
-
5
- # Módulo que provee métodos de deteccion y validacion para MSISDN por el
6
- # header de HTTP 'Msisdn':
7
- # - Comcel Colombia
8
- module FromXUpSubnoHttpRequestHeader
9
-
10
- extend ActiveSupport::Concern
11
-
12
- module ClassMethods
13
- def extract_from_x_up_subno_http_request_header(request)
14
- header_name = 'X-Up-Subno'
15
- header_env_key = "HTTP_#{header_name.gsub('-','_').upcase}"
16
-
17
- isdn_attributes = nil
18
-
19
- isdn_attributes = if msisdn = request.env[header_env_key] and msisdn.strip.length >= 8
20
- msisdn.strip!
21
- detection_cues = {
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
- isdn_attributes
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, :detection_cues
9
+ attr_reader :id, :mobile_country_code, :mobile_network_code, :http_request_info
10
10
  alias_method :to_s, :id
11
11
 
12
- include MobileSubscriber::Detection::FromMsisdnHttpRequestHeader
13
- include MobileSubscriber::Detection::FromXNokiaMsisdnHttpRequestHeader
14
- include MobileSubscriber::Detection::FromXUpCallingLineIdHttpRequestHeader
15
- include MobileSubscriber::Detection::FromXUpChMsisdnHttpRequestHeader
16
- include MobileSubscriber::Detection::FromXUpSubnoHttpRequestHeader
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
- @detection_cues = attributes.delete :detection_cues
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
- detected_attributes = self.methods.select do |x|
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.sort.reduce(nil) do |attrs, detection_method|
65
- attrs = self.send detection_method, request unless attrs.present?
66
- attrs
67
- end
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 detected_attributes.present?
70
- validated_isdn = new(detected_attributes)
71
+ if detection.present?
72
+ validated_isdn = new(detection)
71
73
  validated_isdn.send :http_validated!
72
74
  validated_isdn
73
75
  end
@@ -1,3 +1,3 @@
1
1
  module MobileSubscriber
2
- VERSION = "0.0.1.alpha5"
2
+ VERSION = "0.0.1.beta1"
3
3
  end
@@ -2,16 +2,20 @@ require "spec_helper"
2
2
 
3
3
  describe MobileSubscriber::Detection::FromMsisdnHttpRequestHeader do
4
4
 
5
- include described_class::ClassMethods
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 test_request
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::ClassMethods
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 test_request
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::ClassMethods
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 test_request
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
@@ -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(
@@ -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.alpha5
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-07 00:00:00.000000000 Z
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