Commit 2201e360ff31d4c08f1449cb3dafcdaf0d270a90

Authored by Geoffrey PREUD'HOMME
1 parent bc6e4c53

Le login se fait désormais de manière encryptée

Makefile 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +config/ci_com_pub.pem: config/ci_com.pem
  2 + openssl rsa -pubout -in $< -out $@
  3 + chmod 777 $@
  4 +
  5 +config/ci_com.pem:
  6 + openssl genrsa -out $@ 1024
  7 + chmod 700 $@
... ...
app/controllers/decrypt.js 0 → 100644
... ... @@ -0,0 +1,36 @@
  1 +var ursa = require('ursa');
  2 +var fs = require('fs');
  3 +
  4 +var decrypt = {};
  5 +
  6 +decrypt.decrypter = false;
  7 +
  8 +decrypt.whenOk = function (cb) {
  9 + if (this.encrypter) {
  10 + cb();
  11 + } else {
  12 + this.prepare(cb);
  13 + }
  14 +};
  15 +
  16 +decrypt.prepare = function (cb) {
  17 + fs.readFile('config/ci_com.pem', function(err, data) {
  18 + if (err) {
  19 + throw err;
  20 + }
  21 + this.decrypter = ursa.createPrivateKey(data);
  22 + cb();
  23 + });
  24 +};
  25 +
  26 +decrypt.preload = function(cb) {
  27 + this.whenOk(cb);
  28 +};
  29 +
  30 +decrypt.decrypt = function (string, cb) {
  31 + this.whenOk(function() {
  32 + cb(this.decrypter.decrypt(string, 'base64', 'utf8', ursa.RSA_PKCS1_PADDING));
  33 + });
  34 +};
  35 +
  36 +module.exports = decrypt;
... ...
app/controllers/sessions.js
... ... @@ -115,4 +115,4 @@ sessions.open = function (data, cb) {
115 115 });
116 116 }
117 117  
118   -module.exports = sessions;
119 118 \ No newline at end of file
  119 +module.exports = sessions;
... ...
app/routes/api.js
1 1 var membres = require('../controllers/membres');
2 2 var sessions = require('../controllers/sessions');
  3 +var decrypt = require('../controllers/decrypt');
3 4 var express = require('express');
4 5  
5   -var api = express()
  6 +var api = express();
6 7  
7 8 // Sessions
8 9 api.get('/session', function (req, res) { // Informations sur la session
9   - if (req.cookies && req.cookies.session) {
10   - sessions.use(req.cookies.session, function (err) {
11   - if (err) {
12   - res.send(err)
13   - } else {
14   - res.send(sessions.cur)
15   - }
16   - })
17   - // TODO si pas bon : res.clearCookie('session')
18   - } else {
19   - res.send('missing');
20   - }
  10 + if (req.cookies && req.cookies.session) {
  11 + sessions.use(req.cookies.session, function (err) {
  12 + if (err) {
  13 + res.send(err);
  14 + } else {
  15 + res.send(sessions.cur);
  16 + }
  17 + });
  18 + // TODO si pas bon : res.clearCookie('session')
  19 + } else {
  20 + res.send('missing');
  21 + }
21 22 });
22 23  
23 24 api.post('/session', function (req, res) { // Se connecter
24   - sessions.open(req.body, function (err) {
25   - if (err) {
26   - res.send(err)
27   - } else {
28   - res.cookie('session', sessions.cur._id);
29   - res.send(sessions.cur)
30   - }
31   - })
32   -})
  25 + decrypt.decrypt(req.body[0], function (data) {
  26 + sessions.open(JSON.parse(data), function (err) {
  27 + if (err) {
  28 + res.send(err);
  29 + } else {
  30 + res.cookie('session', sessions.cur._id);
  31 + res.send(sessions.cur);
  32 + }
  33 + });
  34 + });
  35 +});
33 36  
34 37 api.delete('/session', function (req, res) { // Se déconnecter
35   - if (req.cookies.session) {
36   - sessions.delete(req.cookies.session, function () {
37   - res.clearCookie('session');
38   - res.end()
39   - })
40   - } else {
41   - res.send('missing')
42   - }
43   -})
  38 + if (req.cookies.session) {
  39 + sessions.delete(req.cookies.session, function () {
  40 + res.clearCookie('session');
  41 + res.end();
  42 + });
  43 + } else {
  44 + res.send('missing');
  45 + }
  46 +});
44 47  
45 48 ifPermission = function (req, res, perm, cb) {
46   - sessions.use(req.cookies.session, function (err) {
47   - if (err) {
48   - res.status(403).end()
49   - } else {
50   - if (sessions.cur[perm]) {
51   - cb()
52   - } else {
53   - res.status(403).end()
54   - }
55   - }
56   - })
57   -}
  49 + sessions.use(req.cookies.session, function (err) {
  50 + if (err) {
  51 + res.status(403).end();
  52 + } else {
  53 + if (sessions.cur[perm]) {
  54 + cb();
  55 + } else {
  56 + res.status(403).end();
  57 + }
  58 + }
  59 + });
  60 +};
58 61  
59 62  
60 63 // Membres
61 64 api.get('/membres', function (req, res) { // Liste des membres
62   - membres.list(function (err, membres) {
63   - if (err)
64   - res.send(err);
65   - res.json(membres);
66   - });
  65 + membres.list(function (err, membres) {
  66 + if (err)
  67 + res.send(err);
  68 + res.json(membres);
  69 + });
67 70 });
68 71  
69 72 api.post('/membres', function (req, res) { // Ajout d'un membre
70   - ifPermission(req, res, 'canAddMembre', function () {
71   - membres.add(req.body, function (err, membre) {
72   - if (err)
73   - res.send(err);
74   - membres.list(function (err, membres) {
75   - if (err)
76   - res.send(err);
77   - res.json(membres);
78   - });
79   - });
80   - })
  73 + ifPermission(req, res, 'canAddMembre', function () {
  74 + membres.add(req.body, function (err, membre) {
  75 + if (err)
  76 + res.send(err);
  77 + membres.list(function (err, membres) {
  78 + if (err)
  79 + res.send(err);
  80 + res.json(membres);
  81 + });
  82 + });
  83 + });
81 84 });
82 85  
83 86 api.delete('/membres/:membre_id', function (req, res) { // Supression d'un membre
84   - ifPermission(req, res, 'canDelMembre', function () {
85   - membres.remove(req.params.membre_id, function (err, membre) {
86   - if (err)
87   - res.send(err);
88   - membres.list(function (err, membres) {
89   - if (err)
90   - res.send(err);
91   - res.json(membres);
92   - });
93   - });
94   - })
95   -})
  87 + ifPermission(req, res, 'canDelMembre', function () {
  88 + membres.remove(req.params.membre_id, function (err, membre) {
  89 + if (err)
  90 + res.send(err);
  91 + membres.list(function (err, membres) {
  92 + if (err)
  93 + res.send(err);
  94 + res.json(membres);
  95 + });
  96 + });
  97 + });
  98 +});
96 99  
97   -module.exports = api;
98 100 \ No newline at end of file
  101 +module.exports = api;
... ...
bower.json
... ... @@ -5,6 +5,7 @@
5 5 "font-awesome": "latest",
6 6 "angular": "latest",
7 7 "angular-route": "latest",
8   - "bootswatch-dist": "3.3.2-cerulean"
  8 + "bootswatch-dist": "3.3.2-cerulean",
  9 + "jsencrypt": "~2.1.0"
9 10 }
10 11 }
... ...
package.json
... ... @@ -9,6 +9,7 @@
9 9 "method-override": "^2.3.1",
10 10 "mongoose": "^3.8.25",
11 11 "morgan": "^1.5.1",
12   - "node-line-reader": "0.0.2"
  12 + "node-line-reader": "0.0.2",
  13 + "ursa": "^0.8.4"
13 14 }
14 15 }
... ...
public/com/ci_com.pem 0 → 100644
... ... @@ -0,0 +1 @@
  1 +Même pas en rêve !
... ...
public/com/ci_com_priv.pem 0 → 120000
... ... @@ -0,0 +1 @@
  1 +ci_com.pem
0 2 \ No newline at end of file
... ...
public/com/ci_com_pub.pem 0 → 120000
... ... @@ -0,0 +1 @@
  1 +../../config/ci_com_pub.pem
0 2 \ No newline at end of file
... ...
public/js/app.js
1   -angular.module('ciApp', ['ngRoute', 'appRoutes', 'SessionsServ', 'SessionsCtrl', 'ConnectCtrl', 'MembreCtrl']);
2 1 \ No newline at end of file
  2 +angular.module('ciApp', ['ngRoute', 'appRoutes', 'EncryptServ', 'SessionsServ', 'SessionsCtrl', 'ConnectCtrl', 'MembreCtrl']);
... ...
public/js/controllers/ConnectCtrl.js
1   -angular.module('ConnectCtrl', []).controller('ConnectController', ['$scope', 'SessionService',
2   - function ($scope, SessionService) {
3   - $scope.connect = {
4   - connect: function () {
5   - SessionService.connect($scope.connect.login, $scope.connect.pass)
6   - }
7   - }
8   - }
9   -]);
10 1 \ No newline at end of file
  2 +angular.module('ConnectCtrl', []).controller('ConnectController', ['$scope', 'SessionService', 'EncryptService',
  3 + function ($scope, SessionService, EncryptService) {
  4 + EncryptService.preload(function () {
  5 + return undefined;
  6 + });
  7 + $scope.connect = {
  8 + connect: function () {
  9 + SessionService.connect($scope.connect.login, $scope.connect.pass);
  10 + }
  11 + };
  12 + }
  13 +]);
... ...
public/js/services/EncryptServ.js 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +angular.module('EncryptServ', []).service('EncryptService', ['$http',
  2 + function ($http) {
  3 + a = {
  4 + encrypter: false,
  5 + whenOk: function (cb) {
  6 + if (this.encrypter) {
  7 + cb();
  8 + } else {
  9 + this.prepare(cb);
  10 + }
  11 + },
  12 + prepare: function (cb) {
  13 + $http.get('/com/ci_com_pub.pem').success(function (key) {
  14 + this.encrypter = new JSEncrypt();
  15 + this.encrypter.setPublicKey(key);
  16 + cb();
  17 + });
  18 + },
  19 + preload: function(cb) {
  20 + this.whenOk(cb);
  21 + },
  22 + encrypt: function (string, cb) {
  23 + this.whenOk(function() {
  24 + cb(this.encrypter.encrypt(string));
  25 + });
  26 + }
  27 + };
  28 + return a;
  29 + }
  30 +]);
... ...
public/js/services/SessionServ.js
1   -angular.module('SessionsServ', []).service('SessionService', ['$http',
2   - function ($http) {
3   - a = {
4   - cur: false,
5   - status: 0,
6   - changeHandlers: [],
7   - onChange: function (fun) {
8   - this.changeHandlers.push(fun)
9   - },
10   - triggerChange: function () {
11   - for (fun in this.changeHandlers) {
12   - this.changeHandlers[fun]()
13   - }
14   - },
15   - updateSessionInfos: function (data) {
16   - console.log("Connection:", data)
17   - if (typeof data === 'object') {
18   - this.cur = data
19   - } else {
20   - this.cur = false
21   - }
22   - this.triggerChange()
23   - },
24   - get: function (cb) { // Fetch infos if needed
25   - if (status == 0) {
26   - this.status = 1 // Fetching
27   - _this = this
28   - // TODO Verify if cookies to prevent uneeded request
29   - $http.get('/api/session').success(function (body) {
30   - _this.updateSessionInfos(body)
31   - if (cb) {
32   - if (this.logged) {
33   - cb(null)
34   - } else {
35   - cb(body)
36   - }
37   - }
38   - })
39   - } else {
40   - console.warn("Unnecessary get() call")
41   - }
42   - },
43   - connect: function (login, pass, cb) {
44   - _this = this
45   - $http.post('/api/session', {
46   - login: login,
47   - pass: pass
48   - }).success(function (body) {
49   - _this.updateSessionInfos(body)
50   - if (cb) {
51   - if (this.logged) {
52   - cb(null)
53   - } else {
54   - cb(body)
55   - }
56   - }
57   - })
58   - },
59   - disconnect: function () {
60   - this.updateSessionInfos(false)
61   - $http.delete('/api/session')
  1 +angular.module('SessionsServ', []).service('SessionService', ['$http', 'EncryptService',
  2 + function ($http, EncryptService) {
  3 + a = {
  4 + cur: false,
  5 + status: 0,
  6 + changeHandlers: [],
  7 + onChange: function (fun) {
  8 + this.changeHandlers.push(fun);
  9 + },
  10 + triggerChange: function () {
  11 + for (var fun in this.changeHandlers) {
  12 + this.changeHandlers[fun]();
  13 + }
  14 + },
  15 + updateSessionInfos: function (data) {
  16 + console.log("Connection:", data);
  17 + if (typeof data === 'object') {
  18 + this.cur = data;
  19 + } else {
  20 + this.cur = false;
  21 + }
  22 + this.triggerChange();
  23 + },
  24 + get: function (cb) { // Fetch infos if needed
  25 + if (status === 0) {
  26 + this.status = 1; // Fetching
  27 + _this = this;
  28 + // TODO Verify if cookies to prevent uneeded request
  29 + $http.get('/api/session').success(function (body) {
  30 + _this.updateSessionInfos(body);
  31 + if (cb) {
  32 + if (this.logged) {
  33 + cb(null);
  34 + } else {
  35 + cb(body);
  36 + }
62 37 }
  38 + });
  39 + } else {
  40 + console.warn("Unnecessary get() call");
63 41 }
64   - a.get()
65   - return a
66   - }
67   -])
68 42 \ No newline at end of file
  43 + },
  44 + connect: function (login, pass, cb) {
  45 + _this = this;
  46 + data = JSON.stringify({
  47 + login: login,
  48 + pass: pass
  49 + });
  50 + EncryptService.encrypt(data, function (dataCrypt) {
  51 + $http.post('/api/session', [dataCrypt]).success(function (body) {
  52 + _this.updateSessionInfos(body);
  53 + if (cb) {
  54 + if (this.logged) {
  55 + cb(null);
  56 + } else {
  57 + cb(body);
  58 + }
  59 + }
  60 + });
  61 + });
  62 + },
  63 + disconnect: function () {
  64 + this.updateSessionInfos(false);
  65 + $http.delete('/api/session');
  66 + }
  67 + };
  68 + a.get();
  69 + return a;
  70 + }
  71 +]);
... ...
public/views/connect.html
1 1 <div class="container">
2 2 <h1>Se connecter</h1>
3   - <div class="alert alert-warning" role="alert"><strong>Faites attention !</strong> Ce site internet est encore en développement, les connexions ne sont pas sécurisées.<br/>
4   - Soyez sûr d'être sur un réseau sécurisé tel que celui de Polytech ou de votre box internet avant d'entrer votre mot de passe.</div>
5 3 <form>
6 4 <div class="form-group">
7 5 <label for="login">Identifiant</label>
... ... @@ -13,4 +11,4 @@
13 11 </div>
14 12 <button type="submit" class="btn btn-default" ng-click="connect.connect()">Se connecter</button>
15 13 </form>
16   -</div>
17 14 \ No newline at end of file
  15 +</div>
... ...
public/views/index.html
... ... @@ -11,7 +11,9 @@
11 11 <script src="libs/angular/angular.min.js"></script>
12 12 <script src="libs/angular-route/angular-route.min.js"></script>
13 13 <script src="libs/angular-bootstrap/ui-bootstrap.min.js"></script>
  14 + <script src="libs/jsencrypt/bin/jsencrypt.min.js"></script>
14 15 <script src="js/controllers/MembreCtrl.js"></script>
  16 + <script src="js/services/EncryptServ.js"></script>
15 17 <script src="js/services/SessionServ.js"></script>
16 18 <script src="js/controllers/SessionCtrl.js"></script>
17 19 <script src="js/controllers/ConnectCtrl.js"></script>
... ... @@ -41,4 +43,4 @@
41 43 <div ng-view></div>
42 44 </div>
43 45 </body>
44   -</html>
45 46 \ No newline at end of file
  47 +</html>
... ...