Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Thomas Rientjes
tor-browser-settings
Commits
2d6acb36
Commit
2d6acb36
authored
Mar 31, 2017
by
Thomas Rientjes
Browse files
Refactor security preferences module
parent
e8a90e2c
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/models/nsa-policy.js
0 → 100644
View file @
2d6acb36
/**
* NSA Policy model.
*/
class
NsaPolicy
{
/**
* Creates an NSA Policy.
*/
constructor
()
{
this
.
UNTRUSTED
=
{};
this
.
TRUSTED
=
{
'
js
'
:
true
,
'
webgl
'
:
true
,
'
java
'
:
true
,
'
flash
'
:
true
,
'
silverlight
'
:
true
,
'
plugin
'
:
true
,
'
media
'
:
true
,
'
frame
'
:
true
,
'
font
'
:
true
};
this
.
DEFAULT
=
{
'
frame
'
:
true
};
this
[
'
mozilla.org
'
]
=
1
;
this
[
'
mozilla.com
'
]
=
1
;
this
[
'
mozilla.net
'
]
=
1
;
this
[
'
google.com
'
]
=
1
;
this
[
'
gstatic.com
'
]
=
1
;
this
[
'
googleapis.com
'
]
=
1
;
this
[
'
yahoo.com
'
]
=
1
;
this
[
'
yimg.com
'
]
=
1
;
this
[
'
yahooapis.com
'
]
=
1
;
this
[
'
hotmail.com
'
]
=
1
;
this
[
'
live.com
'
]
=
1
;
this
[
'
wlxrs.com
'
]
=
1
;
this
[
'
securecode.com
'
]
=
1
;
this
[
'
recaptcha.net
'
]
=
1
;
this
[
'
noscript.net
'
]
=
1
;
this
[
'
flashgot.net
'
]
=
1
;
this
[
'
informaction.com
'
]
=
1
;
this
[
'
youtube.com
'
]
=
1
;
this
[
'
ytimg.com
'
]
=
1
;
}
};
exports
.
NsaPolicy
=
NsaPolicy
;
src/modules/security-preferences.js
View file @
2d6acb36
...
...
@@ -13,6 +13,13 @@
*/
var
sdkPreferences
=
require
(
'
sdk/preferences/service
'
);
/**
* The NSA policy model.
*
* @var {NsaPolicy} NsaPolicy
*/
var
{
NsaPolicy
}
=
require
(
'
../models/nsa-policy
'
);
/**
* Contains generic utility functions.
*
...
...
@@ -20,6 +27,13 @@ var sdkPreferences = require('sdk/preferences/service');
*/
var
utilities
=
require
(
'
./utilities.js
'
);
/**
* Indicates whether or not this module has been initialized.
*
* @var {boolean} initialized
*/
var
initialized
=
false
;
/**
* Bindings between preferences and slider levels.
*
...
...
@@ -38,141 +52,221 @@ var preferenceBindings = {
'
svg.in-content.enabled
'
:
[
true
,
true
,
false
]
};
// The Security Settings prefs in question.
const
kSliderPref
=
'
extensions.tor-browser-settings@torproject.org.security_level
'
;
const
kCustomPref
=
'
extensions.tor-browser-settings@torproject.org.security_custom
'
;
const
nsaPolicyPref
=
'
extensions.nsa.policy
'
;
const
nsaStandard
=
{
'
js
'
:
true
,
'
webgl
'
:
true
,
'
java
'
:
true
,
'
flash
'
:
true
,
'
silverlight
'
:
true
,
'
plugin
'
:
true
,
'
media
'
:
true
,
'
frame
'
:
true
,
'
font
'
:
true
/**
* Bindings between NSA policy rules and slider levels.
*
* @var {Object} nsaPolicyBindings
*/
var
nsaPolicyBindings
=
{
// NSA policy rule name Standard Safer Safest
'
js
'
:
[
true
,
false
,
false
],
'
webgl
'
:
[
true
,
false
,
false
],
'
java
'
:
[
true
,
false
,
false
],
'
flash
'
:
[
true
,
false
,
false
],
'
silverlight
'
:
[
true
,
false
,
false
],
'
plugin
'
:
[
true
,
false
,
false
],
'
media
'
:
[
true
,
false
,
false
],
'
frame
'
:
[
true
,
false
,
false
],
'
font
'
:
[
true
,
false
,
false
]
};
const
nsaSafest
=
{
'
js
'
:
false
,
'
webgl
'
:
false
,
'
java
'
:
false
,
'
flash
'
:
false
,
'
silverlight
'
:
false
,
'
plugin
'
:
false
,
'
media
'
:
false
,
'
frame
'
:
false
,
'
font
'
:
false
/**
* The NoScript Anywhere policy preference domain.
*
* @constant NSA_POLICY_DOMAIN
* @type {string}
*/
const
NSA_POLICY_DOMAIN
=
'
extensions.nsa.policy
'
;
/**
* The custom security settings preference domain.
*
* @constant SECURITY_CUSTOM_DOMAIN
* @type {string}
*/
const
SECURITY_CUSTOM_DOMAIN
=
'
extensions.tor-browser-settings@torproject.org.security_custom
'
;
/**
* The security level preference domain.
*
* @constant SECURITY_LEVEL_DOMAIN
* @type {string}
*/
const
SECURITY_LEVEL_DOMAIN
=
'
extensions.tor-browser-settings@torproject.org.security_level
'
;
/**
* Generates a NoScript Anywhere policy string.
*
* @returns {string} NSA policy string
* @private
*/
function
generateNsaPolicyString
()
{
let
securityLevel
,
nsaPolicyString
,
nsaPolicy
;
securityLevel
=
sdkPreferences
.
get
(
SECURITY_LEVEL_DOMAIN
);
nsaPolicyString
=
sdkPreferences
.
get
(
NSA_POLICY_DOMAIN
);
try
{
nsaPolicy
=
JSON
.
parse
(
nsaPolicyString
);
}
catch
(
exception
)
{
nsaPolicy
=
new
NsaPolicy
();
}
nsaPolicy
.
UNTRUSTED
=
generateNsaRuleset
(
'
UNTRUSTED
'
,
securityLevel
);
nsaPolicy
.
TRUSTED
=
generateNsaRuleset
(
'
TRUSTED
'
,
securityLevel
);
nsaPolicy
.
DEFAULT
=
generateNsaRuleset
(
'
DEFAULT
'
,
securityLevel
);
return
JSON
.
stringify
(
nsaPolicy
);
};
// ### Prefs
var
generate_nsa_policy
=
function
()
{
let
currentNsaPolicy
=
sdkPreferences
.
get
(
nsaPolicyPref
)
||
'
{"UNTRUSTED":{},"TRUSTED":{"js":true,"webgl":true,"java":true,"flash":true,"silverlight":true,"plugin":true,"media":true,"frame":true,"font":true},"DEFAULT":{"frame":true},"mozilla.org":1,"mozilla.com":1,"mozilla.net":1,"google.com":1,"gstatic.com":1,"googleapis.com":1,"yahoo.com":1,"yimg.com":1,"yahooapis.com":1,"hotmail.com":1,"live.com":1,"wlxrs.com":1,"securecode.com":1,"recaptcha.net":1,"noscript.net":1,"flashgot.net":1,"informaction.com":1,"youtube.com":1,"ytimg.com":1}
'
;
let
securitySliderValue
=
sdkPreferences
.
get
(
kSliderPref
);
currentNsaPolicy
=
JSON
.
parse
(
currentNsaPolicy
);
currentNsaPolicy
.
UNTRUSTED
=
{};
if
(
securitySliderValue
===
0
||
securitySliderValue
===
'
0
'
)
{
currentNsaPolicy
.
TRUSTED
=
nsaStandard
;
currentNsaPolicy
.
DEFAULT
=
nsaStandard
;
}
else
{
currentNsaPolicy
.
TRUSTED
=
nsaSafest
;
currentNsaPolicy
.
DEFAULT
=
nsaSafest
;
}
return
JSON
.
stringify
(
currentNsaPolicy
);
/**
* Generates a NoScript Anywhere ruleset.
*
* @returns {Object} NSA ruleset
* @private
*/
function
generateNsaRuleset
(
nsaRulesetName
,
securityLevel
)
{
let
nsaRuleset
=
{};
if
(
nsaRulesetName
===
'
TRUSTED
'
||
nsaRulesetName
===
'
DEFAULT
'
)
{
let
nsaRuleNames
=
Object
.
keys
(
nsaPolicyBindings
);
nsaRuleNames
.
forEach
(
function
(
nsaRuleName
)
{
nsaRuleset
[
nsaRuleName
]
=
nsaPolicyBindings
[
nsaRuleName
][
securityLevel
];
});
}
return
nsaRuleset
;
};
// __write_setting_to_prefs(settingIndex)__.
// Take a given setting index and write the appropriate pref values
// to the pref database.
var
write_setting_to_prefs
=
function
(
settingIndex
)
{
Object
.
keys
(
preferenceBindings
).
forEach
(
prefName
=>
sdkPreferences
.
set
(
prefName
,
preferenceBindings
[
prefName
][
settingIndex
]));
/**
* Applies preference bindings for a given security level.
*
* @param {number} securityLevel
* @private
*/
function
applyPreferenceBindings
(
securityLevel
)
{
let
preferenceNames
=
Object
.
keys
(
preferenceBindings
);
preferenceNames
.
forEach
(
function
(
preferenceName
)
{
let
preferenceValue
=
preferenceBindings
[
preferenceName
][
securityLevel
];
sdkPreferences
.
set
(
preferenceName
,
preferenceValue
);
});
};
// __read_setting_from_prefs()__.
// Read the current pref values, and decide if any of our
// security settings matches. Otherwise return null.
var
read_setting_from_prefs
=
function
()
{
let
prefNames
=
Object
.
keys
(
preferenceBindings
);
for
(
let
settingIndex
of
[
0
,
1
,
2
])
{
let
possibleSetting
=
true
;
// For the given settingIndex, check if all current pref values
// match the setting.
for
(
let
prefName
of
prefNames
)
{
if
(
preferenceBindings
[
prefName
][
settingIndex
]
!==
sdkPreferences
.
get
(
prefName
))
{
possibleSetting
=
false
;
}
}
if
(
possibleSetting
)
{
// We have a match!
return
settingIndex
;
/**
* Attempts to determine the current security level.
*
* @returns {number|null} Security level or null
* @private
*/
function
determineCurrentSecurityLevel
()
{
let
preferenceNames
=
Object
.
keys
(
preferenceBindings
);
for
(
let
securityLevel
of
[
0
,
1
,
2
])
{
let
perfectMatch
=
true
;
for
(
let
preferenceName
of
preferenceNames
)
{
let
expectedValue
,
actualValue
;
expectedValue
=
preferenceBindings
[
preferenceName
][
securityLevel
];
actualValue
=
sdkPreferences
.
get
(
preferenceName
);
if
(
expectedValue
!==
actualValue
)
{
perfectMatch
=
false
;
break
;
}
}
if
(
perfectMatch
===
true
)
{
return
securityLevel
;
}
}
}
// No matching setting; return null.
return
null
;
return
null
;
};
// __watch_security_prefs(onSettingChanged)__.
// Whenever a pref bound to the security slider changes, onSettingChanged
// is called with the new security setting value (0,1,2 or null).
// Returns a zero-arg function that ends this binding.
var
watch_security_prefs
=
function
(
onSettingChanged
)
{
let
prefNames
=
Object
.
keys
(
preferenceBindings
);
let
unbindFuncs
=
[];
for
(
let
prefName
of
prefNames
)
{
unbindFuncs
.
push
(
utilities
.
bindChangeHandlerToPreference
(
prefName
,
()
=>
onSettingChanged
(
read_setting_from_prefs
()),
true
));
}
// Call all the unbind functions.
return
()
=>
unbindFuncs
.
forEach
(
unbind
=>
unbind
());
/**
* Adds change observers to browser preferences.
*
* @returns {function} Observer unbinder
* @private
*/
function
addObserversToPreferences
(
handler
)
{
let
preferenceNames
,
unbindFunctions
;
preferenceNames
=
Object
.
keys
(
preferenceBindings
);
unbindFunctions
=
[];
for
(
let
preferenceName
of
preferenceNames
)
{
let
unbindObserver
=
utilities
.
addObserverToPreference
(
preferenceName
,
function
()
{
let
currentSecurityLevel
=
determineCurrentSecurityLevel
();
return
handler
(
currentSecurityLevel
);
},
true
);
unbindFunctions
.
push
(
unbindObserver
);
}
// Can be invoked to unbind all previously registered observers.
return
()
=>
unbindFunctions
.
forEach
(
unbind
=>
unbind
());
};
// __initialized__.
// Have we called initialize() yet?
var
initialized
=
false
;
/**
* Defines the behavior of the various preference bindings.
*/
exports
.
initialize
=
function
()
{
if
(
initialized
===
true
)
{
return
;
}
// __initialize()__.
// Defines the behavior of "extensions.torbutton.security_custom",
// "extensions.torbutton.security_slider", and the security-sensitive
// prefs declared in preferenceBindings.
var
initialize
=
function
()
{
// Only run once.
if
(
initialized
)
{
return
;
}
initialized
=
true
;
sdkPreferences
.
set
(
nsaPolicyPref
,
generate_nsa_policy
());
// When security_custom is set to false, apply security_slider setting
// to the security-sensitive prefs.
utilities
.
bindChangeHandlerToPreference
(
kCustomPref
,
function
(
custom
)
{
if
(
custom
===
false
)
{
write_setting_to_prefs
(
sdkPreferences
.
get
(
kSliderPref
));
// Signal module initialization.
initialized
=
true
;
// Observer for the custom security level preference.
utilities
.
addObserverToPreference
(
SECURITY_CUSTOM_DOMAIN
,
function
(
customized
)
{
if
(
customized
===
false
)
{
let
securityLevel
=
sdkPreferences
.
get
(
SECURITY_LEVEL_DOMAIN
);
sdkPreferences
.
set
(
NSA_POLICY_DOMAIN
,
generateNsaPolicyString
());
applyPreferenceBindings
(
securityLevel
);
}
},
true
);
// If security_slider is given a new value, then security_custom should
// be set to false.
utilities
.
bindChangeHandlerToPreference
(
kSliderPref
,
function
(
prefIndex
)
{
sdkPreferences
.
set
(
kCustomPref
,
false
);
sdkPreferences
.
set
(
nsaPolicyPref
,
generate_nsa_policy
());
write_setting_to_prefs
(
prefIndex
);
});
// If a security-sensitive pref changes, then decide if the set of pref values
// constitutes a security_slider setting or a custom value.
watch_security_prefs
(
settingIndex
=>
{
if
(
settingIndex
===
null
)
{
sdkPreferences
.
set
(
kCustomPref
,
true
);
}
else
{
sdkPreferences
.
set
(
kSliderPref
,
settingIndex
);
sdkPreferences
.
set
(
kCustomPref
,
false
);
}
});
};
// Export initialize() function for external use.
exports
.
initialize
=
initialize
;
// Observer for the security level preference.
utilities
.
addObserverToPreference
(
SECURITY_LEVEL_DOMAIN
,
function
(
securityLevel
)
{
sdkPreferences
.
set
(
SECURITY_CUSTOM_DOMAIN
,
false
);
sdkPreferences
.
set
(
NSA_POLICY_DOMAIN
,
generateNsaPolicyString
());
applyPreferenceBindings
(
securityLevel
);
});
// Adds observers to related browser preferences.
addObserversToPreferences
(
function
(
securityLevel
)
{
if
(
securityLevel
===
null
)
{
sdkPreferences
.
set
(
SECURITY_CUSTOM_DOMAIN
,
true
);
}
else
{
sdkPreferences
.
set
(
SECURITY_LEVEL_DOMAIN
,
securityLevel
);
sdkPreferences
.
set
(
SECURITY_CUSTOM_DOMAIN
,
false
);
}
});
};
src/modules/utilities.js
View file @
2d6acb36
...
...
@@ -30,7 +30,7 @@ var sdkPreferences = require('sdk/preferences/service');
/**
* Bind a change handler to a specific preference domain.
*/
exports
.
bindChangeHandl
erToPreference
=
function
(
domain
,
handler
,
initialize
=
false
)
{
exports
.
addObserv
erToPreference
=
function
(
domain
,
handler
,
initialize
=
false
)
{
let
updatePreference
,
observer
;
...
...
Thomas Rientjes
@Synzvato
mentioned in issue
#17 (closed)
·
Apr 07, 2017
mentioned in issue
#17 (closed)
mentioned in issue #17
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment