1
|
|
|
var express = require('express');
|
2
|
|
|
var extend = require('extend');
|
3
|
|
|
var request = require('request');
|
4
|
|
|
|
5
|
|
|
// ------------------------------------------
|
6
|
|
|
// CONSTRUCTOR
|
7
|
|
|
// ------------------------------------------
|
8
|
|
|
|
9
|
|
|
var init = function(){
|
10
|
|
|
info('Starting PrivacyManager ...');
|
11
|
|
|
salt();
|
12
|
|
|
|
13
|
|
|
return PrivacyManager;
|
14
|
|
|
}
|
15
|
|
|
|
16
|
|
|
// ------------------------------------------
|
17
|
|
|
// USERS
|
18
|
|
|
// ------------------------------------------
|
19
|
|
|
|
20
|
|
|
var findByUsername = function (username, fn) {
|
21
|
|
|
setTimeout(function(){ // slow bruteforce
|
22
|
|
|
|
23
|
|
|
var user = Config.auth['local-users'][username]
|
|
|
|
|
24
|
|
|
if (user){ return fn(null, user); }
|
25
|
|
|
return fn(null, null);
|
26
|
|
|
|
27
|
|
|
}, 1000);
|
28
|
|
|
}
|
29
|
|
|
|
30
|
|
|
// ------------------------------------------
|
31
|
|
|
// PASSPORT
|
32
|
|
|
// ------------------------------------------
|
33
|
|
|
|
34
|
|
|
var passport = require('passport');
|
35
|
|
|
|
36
|
|
|
passport.serializeUser (function(user, done) { /*info('serializeUser', user);*/ done(null, user); });
|
37
|
|
|
passport.deserializeUser(function(obj, done) { /*info('deserializeUser', obj);*/ done(null, obj); });
|
38
|
|
|
|
39
|
|
|
// ------------------------------------------
|
40
|
|
|
// LOCAL STRATEGY
|
41
|
|
|
// ------------------------------------------
|
42
|
|
|
|
43
|
|
|
var setLocalStrategy = function(passport, router){
|
44
|
|
|
router.get('/login', function(req, res, next) {
|
|
|
|
|
45
|
|
|
res.render('portal/login.ejs', { 'redirect' : req.query.redirect });
|
46
|
|
|
});
|
47
|
|
|
|
48
|
|
|
router.post('/login',
|
49
|
|
|
passport.authenticate('local', { failureRedirect: '/login', failureFlash: false }), function(req, res) {
|
50
|
|
|
if (req.body.redirect){
|
51
|
|
|
res.redirect(req.body.redirect);
|
52
|
|
|
} else {
|
53
|
|
|
res.redirect('/');
|
54
|
|
|
}
|
55
|
|
|
}
|
56
|
|
|
);
|
57
|
|
|
|
58
|
|
|
var LocalStrategy = require('passport-local').Strategy;
|
59
|
|
|
passport.use(new LocalStrategy(local));
|
60
|
|
|
}
|
61
|
|
|
|
62
|
|
|
var local = function(username, password, done) {
|
63
|
|
|
process.nextTick(function () {
|
64
|
|
|
findByUsername(username, function(err, user) {
|
65
|
|
|
|
66
|
|
|
if (err) { return done(err); }
|
67
|
|
|
if (!user) { return done(null, false, { message: 'Unknown user ' + username }); }
|
68
|
|
|
|
69
|
|
|
var passHash = hash(password);
|
70
|
|
|
if (user.password != passHash) {
|
71
|
|
|
info('Invalid password');
|
72
|
|
|
return done(null, false, { message: 'Invalid password' });
|
73
|
|
|
}
|
74
|
|
|
|
75
|
|
|
return done(null, user);
|
76
|
|
|
});
|
77
|
|
|
});
|
78
|
|
|
}
|
79
|
|
|
|
80
|
|
|
// ------------------------------------------
|
81
|
|
|
// ROUTER
|
82
|
|
|
// ------------------------------------------
|
83
|
|
|
|
84
|
|
|
var Router = express.Router();
|
85
|
|
|
Router.use(passport.initialize());
|
86
|
|
|
Router.use(passport.session());
|
87
|
|
|
|
88
|
|
|
Router.get('/logout', function(req, res){
|
89
|
|
|
req.logout();
|
90
|
|
|
res.redirect('/');
|
91
|
|
|
});
|
92
|
|
|
|
93
|
|
|
// Set local strategy
|
94
|
|
|
setLocalStrategy(passport, Router);
|
95
|
|
|
|
96
|
|
|
// Set google strategy
|
97
|
|
|
// setGoogleStrategy(passport, Router);
|
98
|
|
|
|
99
|
|
|
// Security
|
100
|
|
|
Router.all('*', function(req, res, next) {
|
101
|
|
|
|
102
|
|
|
// Security Hole: ByPass for client
|
103
|
|
|
if ( req.path.startsWith('/sarah')
|
104
|
|
|
|| req.path.startsWith('/askme')
|
105
|
|
|
|| req.path.startsWith('/standby')){
|
106
|
|
|
return next();
|
107
|
|
|
}
|
108
|
|
|
|
109
|
|
|
// Set user authentication
|
110
|
|
|
if (Config.auth && Config.auth['local-users']){
|
|
|
|
|
111
|
|
|
if (!req.isAuthenticated()){
|
112
|
|
|
|
113
|
|
|
var redirectURL = encodeURIComponent(req.url);
|
114
|
|
|
return res.redirect('/login?redirect='+redirectURL); }
|
115
|
|
|
} else { req.user = { displayName : '' }}
|
116
|
|
|
|
117
|
|
|
next();
|
|
|
|
|
118
|
|
|
});
|
119
|
|
|
|
120
|
|
|
Router.get('/profile', function(req, res){
|
121
|
|
|
res.render('portal/profile.ejs', { "user" : req.user });
|
122
|
|
|
});
|
123
|
|
|
|
124
|
|
|
Router.post('/profile', function(req, res){
|
125
|
|
|
|
126
|
|
|
var username = req.body.username;
|
|
|
|
|
127
|
|
|
var password = req.body.password;
|
128
|
|
|
var newPassword = req.body.newpassword;
|
129
|
|
|
var displayName = req.body.displayname;
|
130
|
|
|
|
131
|
|
|
// Retrieve user
|
132
|
|
|
var user = Config.auth['local-users'][req.user.login];
|
|
|
|
|
133
|
|
|
|
134
|
|
|
// Check Old password
|
135
|
|
|
var oldHash = hash(password);
|
136
|
|
|
if (user.password !== oldHash){
|
137
|
|
|
res.redirect('/');
|
138
|
|
|
return;
|
139
|
|
|
}
|
140
|
|
|
|
141
|
|
|
// Update new password
|
142
|
|
|
var newHash = hash(newPassword);
|
143
|
|
|
user.password = newHash;
|
144
|
|
|
user.displayName = displayName;
|
145
|
|
|
SARAH.ConfigManager.save();
|
|
|
|
|
146
|
|
|
|
147
|
|
|
res.redirect('/');
|
148
|
|
|
});
|
149
|
|
|
|
150
|
|
|
Router.get('/profile/delete', function(req, res){
|
|
|
|
|
151
|
|
|
delete Config.auth['local-users'][req.query.id]
|
|
|
|
|
152
|
|
|
SARAH.ConfigManager.save();
|
|
|
|
|
153
|
|
|
});
|
154
|
|
|
|
155
|
|
|
Router.all('/profile/create', function(req, res){
|
156
|
|
|
var msg = undefined;
|
|
|
|
|
157
|
|
|
var op = req.body.op;
|
158
|
|
|
|
159
|
|
|
if (op){
|
160
|
|
|
if (req.body.login && req.body.password && req.body.displayname){
|
161
|
|
|
Config.auth['local-users'][req.body.login] = {
|
|
|
|
|
162
|
|
|
login : req.body.login,
|
163
|
|
|
password : hash(req.body.password),
|
164
|
|
|
displayName : req.body.displayname,
|
165
|
|
|
}
|
166
|
|
|
SARAH.ConfigManager.save();
|
|
|
|
|
167
|
|
|
} else { msg = i18n('portal.error.missing'); }
|
168
|
|
|
}
|
169
|
|
|
|
170
|
|
|
res.render('portal/modal-profile.ejs', { 'message': msg, 'op': op });
|
171
|
|
|
});
|
172
|
|
|
|
173
|
|
|
// ------------------------------------------
|
174
|
|
|
// CRYPTO
|
175
|
|
|
// ------------------------------------------
|
176
|
|
|
|
177
|
|
|
var bcrypt = require('bcryptjs');
|
178
|
|
|
|
179
|
|
|
var ITERATION = 10000;
|
180
|
|
|
var hash = function(password){
|
181
|
|
|
var salt = Config.auth['local-salt'];
|
|
|
|
|
182
|
|
|
// salt = new Buffer(salt, 'hex');
|
183
|
|
|
//var key = Crypto.pbkdf2Sync(password, salt, ITERATION, 64);
|
184
|
|
|
//var hash = 'pbkdf2$' + ITERATION + '$' + key.toString('hex') + '$' + salt.toString('hex');
|
185
|
|
|
var hash = bcrypt.hashSync(password, salt);
|
186
|
|
|
return hash;
|
187
|
|
|
}
|
188
|
|
|
|
189
|
|
|
var salt = function(){
|
190
|
|
|
if (Config.auth['local-salt'] != false) return;
|
|
|
|
|
191
|
|
|
|
192
|
|
|
// var salt = ('salt' + (Math.random()*10000)).replace('.','0');
|
193
|
|
|
var salt = bcrypt.genSaltSync(10);
|
194
|
|
|
var sarahId = 'uid-' + (new Date()).getTime();
|
195
|
|
|
registerSARAH(sarahId);
|
196
|
|
|
|
197
|
|
|
Config.auth['local-uid'] = sarahId
|
198
|
|
|
Config.auth['local-salt'] = salt
|
199
|
|
|
Config.auth['local-users'] = Config.auth['local-users'] || {};
|
200
|
|
|
Config.auth['local-users']['admin'] = Config.auth['local-users']['admin'] || {};
|
201
|
|
|
|
202
|
|
|
var admin = Config.auth['local-users']['admin'];
|
203
|
|
|
admin.login = 'admin';
|
204
|
|
|
admin.password = hash('password');
|
205
|
|
|
admin.displayName = 'Admin';
|
206
|
|
|
SARAH.ConfigManager.save();
|
|
|
|
|
207
|
|
|
}
|
208
|
|
|
|
209
|
|
|
var AMZID = '5eVBwYTHp21nzkXrcCC6e4UM93Pr2QMX5cLeD50S';
|
210
|
|
|
var registerSARAH = function(id){
|
211
|
|
|
var url = 'http://tracker.sarah.encausse.net';
|
212
|
|
|
request({
|
213
|
|
|
'uri' : url+'?trackerId='+id,
|
214
|
|
|
'json' : true,
|
215
|
|
|
'headers': {'x-api-key': AMZID }
|
216
|
|
|
},
|
217
|
|
|
function (err, response, json){
|
|
|
|
|
218
|
|
|
if (err || response.statusCode != 200) {
|
|
|
|
|
219
|
|
|
return warn("Can't register SARAH into the Cloud", err, response);
|
220
|
|
|
}
|
221
|
|
|
});
|
222
|
|
|
}
|
223
|
|
|
|
224
|
|
|
|
225
|
|
|
// ------------------------------------------
|
226
|
|
|
// PUBLIC
|
227
|
|
|
// ------------------------------------------
|
228
|
|
|
|
229
|
|
|
var PrivacyManager = {
|
230
|
|
|
'init' : init,
|
231
|
|
|
'Router' : Router
|
232
|
|
|
}
|
233
|
|
|
|
234
|
|
|
// Exports Manager
|
235
|
|
|
exports.init = PrivacyManager.init; |
This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.
To learn more about declaring variables in Javascript, see the MDN.