diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2016-08-25 17:57:37 +0200 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2016-08-25 17:57:37 +0200 |
commit | 26d7d31ba3b1d26ea9a51e8626e4a4537867db94 (patch) | |
tree | 988da4baa1397aaaf46a3c131918257fee4bc34f | |
parent | f84a89f0e7e9595d2b6f6dd59181c01f562a4239 (diff) | |
download | PeerTube-26d7d31ba3b1d26ea9a51e8626e4a4537867db94.tar.gz PeerTube-26d7d31ba3b1d26ea9a51e8626e4a4537867db94.tar.zst PeerTube-26d7d31ba3b1d26ea9a51e8626e4a4537867db94.zip |
Server: encrypt password in database
-rw-r--r-- | package.json | 1 | ||||
-rw-r--r-- | server/helpers/peertube-crypto.js | 21 | ||||
-rw-r--r-- | server/initializers/constants.js | 3 | ||||
-rw-r--r-- | server/initializers/installer.js | 4 | ||||
-rw-r--r-- | server/lib/oauth-model.js | 17 | ||||
-rw-r--r-- | server/models/user.js | 43 |
6 files changed, 74 insertions, 15 deletions
diff --git a/package.json b/package.json index c83ede5c2..5a215c7b9 100644 --- a/package.json +++ b/package.json | |||
@@ -35,6 +35,7 @@ | |||
35 | }, | 35 | }, |
36 | "dependencies": { | 36 | "dependencies": { |
37 | "async": "^2.0.0", | 37 | "async": "^2.0.0", |
38 | "bcrypt": "^0.8.7", | ||
38 | "bittorrent-tracker": "^8.0.0", | 39 | "bittorrent-tracker": "^8.0.0", |
39 | "body-parser": "^1.12.4", | 40 | "body-parser": "^1.12.4", |
40 | "concurrently": "^2.0.0", | 41 | "concurrently": "^2.0.0", |
diff --git a/server/helpers/peertube-crypto.js b/server/helpers/peertube-crypto.js index ef130ea5c..4783e9965 100644 --- a/server/helpers/peertube-crypto.js +++ b/server/helpers/peertube-crypto.js | |||
@@ -1,5 +1,6 @@ | |||
1 | 'use strict' | 1 | 'use strict' |
2 | 2 | ||
3 | const bcrypt = require('bcrypt') | ||
3 | const crypto = require('crypto') | 4 | const crypto = require('crypto') |
4 | const fs = require('fs') | 5 | const fs = require('fs') |
5 | const openssl = require('openssl-wrapper') | 6 | const openssl = require('openssl-wrapper') |
@@ -12,7 +13,9 @@ const algorithm = 'aes-256-ctr' | |||
12 | 13 | ||
13 | const peertubeCrypto = { | 14 | const peertubeCrypto = { |
14 | checkSignature: checkSignature, | 15 | checkSignature: checkSignature, |
16 | comparePassword: comparePassword, | ||
15 | createCertsIfNotExist: createCertsIfNotExist, | 17 | createCertsIfNotExist: createCertsIfNotExist, |
18 | cryptPassword: cryptPassword, | ||
16 | decrypt: decrypt, | 19 | decrypt: decrypt, |
17 | encrypt: encrypt, | 20 | encrypt: encrypt, |
18 | sign: sign | 21 | sign: sign |
@@ -24,6 +27,14 @@ function checkSignature (publicKey, rawData, hexSignature) { | |||
24 | return isValid | 27 | return isValid |
25 | } | 28 | } |
26 | 29 | ||
30 | function comparePassword (plainPassword, hashPassword, callback) { | ||
31 | bcrypt.compare(plainPassword, hashPassword, function (err, isPasswordMatch) { | ||
32 | if (err) return callback(err) | ||
33 | |||
34 | return callback(null, isPasswordMatch) | ||
35 | }) | ||
36 | } | ||
37 | |||
27 | function createCertsIfNotExist (callback) { | 38 | function createCertsIfNotExist (callback) { |
28 | certsExist(function (exist) { | 39 | certsExist(function (exist) { |
29 | if (exist === true) { | 40 | if (exist === true) { |
@@ -36,6 +47,16 @@ function createCertsIfNotExist (callback) { | |||
36 | }) | 47 | }) |
37 | } | 48 | } |
38 | 49 | ||
50 | function cryptPassword (password, callback) { | ||
51 | bcrypt.genSalt(constants.BCRYPT_SALT_SIZE, function (err, salt) { | ||
52 | if (err) return callback(err) | ||
53 | |||
54 | bcrypt.hash(password, salt, function (err, hash) { | ||
55 | return callback(err, hash) | ||
56 | }) | ||
57 | }) | ||
58 | } | ||
59 | |||
39 | function decrypt (key, data, callback) { | 60 | function decrypt (key, data, callback) { |
40 | fs.readFile(constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem', function (err, file) { | 61 | fs.readFile(constants.CONFIG.STORAGE.CERT_DIR + 'peertube.key.pem', function (err, file) { |
41 | if (err) return callback(err) | 62 | if (err) return callback(err) |
diff --git a/server/initializers/constants.js b/server/initializers/constants.js index ce9f8ad6c..dd4eff493 100644 --- a/server/initializers/constants.js +++ b/server/initializers/constants.js | |||
@@ -6,6 +6,8 @@ const path = require('path') | |||
6 | // API version of our pod | 6 | // API version of our pod |
7 | const API_VERSION = 'v1' | 7 | const API_VERSION = 'v1' |
8 | 8 | ||
9 | const BCRYPT_SALT_SIZE = 10 | ||
10 | |||
9 | const CONFIG = { | 11 | const CONFIG = { |
10 | DATABASE: { | 12 | DATABASE: { |
11 | DBNAME: 'peertube' + config.get('database.suffix'), | 13 | DBNAME: 'peertube' + config.get('database.suffix'), |
@@ -115,6 +117,7 @@ if (isTestInstance() === true) { | |||
115 | 117 | ||
116 | module.exports = { | 118 | module.exports = { |
117 | API_VERSION: API_VERSION, | 119 | API_VERSION: API_VERSION, |
120 | BCRYPT_SALT_SIZE: BCRYPT_SALT_SIZE, | ||
118 | CONFIG: CONFIG, | 121 | CONFIG: CONFIG, |
119 | CONSTRAINTS_FIELDS: CONSTRAINTS_FIELDS, | 122 | CONSTRAINTS_FIELDS: CONSTRAINTS_FIELDS, |
120 | FRIEND_SCORE: FRIEND_SCORE, | 123 | FRIEND_SCORE: FRIEND_SCORE, |
diff --git a/server/initializers/installer.js b/server/initializers/installer.js index c12187871..974402094 100644 --- a/server/initializers/installer.js +++ b/server/initializers/installer.js | |||
@@ -114,8 +114,8 @@ function createOAuthAdminIfNotExist (callback) { | |||
114 | user.save(function (err, createdUser) { | 114 | user.save(function (err, createdUser) { |
115 | if (err) return callback(err) | 115 | if (err) return callback(err) |
116 | 116 | ||
117 | logger.info('Username: ' + createdUser.username) | 117 | logger.info('Username: ' + username) |
118 | logger.info('User password: ' + createdUser.password) | 118 | logger.info('User password: ' + password) |
119 | 119 | ||
120 | return callback(null) | 120 | return callback(null) |
121 | }) | 121 | }) |
diff --git a/server/lib/oauth-model.js b/server/lib/oauth-model.js index d9f8b175a..6dab02fca 100644 --- a/server/lib/oauth-model.js +++ b/server/lib/oauth-model.js | |||
@@ -41,7 +41,22 @@ function getRefreshToken (refreshToken, callback) { | |||
41 | function getUser (username, password) { | 41 | function getUser (username, password) { |
42 | logger.debug('Getting User (username: ' + username + ', password: ' + password + ').') | 42 | logger.debug('Getting User (username: ' + username + ', password: ' + password + ').') |
43 | 43 | ||
44 | return User.getByUsernameAndPassword(username, password) | 44 | return User.getByUsername(username).then(function (user) { |
45 | if (!user) return null | ||
46 | |||
47 | // We need to return a promise | ||
48 | return new Promise(function (resolve, reject) { | ||
49 | return user.isPasswordMatch(password, function (err, isPasswordMatch) { | ||
50 | if (err) return reject(err) | ||
51 | |||
52 | if (isPasswordMatch === true) { | ||
53 | return resolve(user) | ||
54 | } | ||
55 | |||
56 | return resolve(null) | ||
57 | }) | ||
58 | }) | ||
59 | }) | ||
45 | } | 60 | } |
46 | 61 | ||
47 | function revokeToken (token) { | 62 | function revokeToken (token) { |
diff --git a/server/models/user.js b/server/models/user.js index c9c35b3e2..e76aab2ce 100644 --- a/server/models/user.js +++ b/server/models/user.js | |||
@@ -2,6 +2,7 @@ const mongoose = require('mongoose') | |||
2 | 2 | ||
3 | const customUsersValidators = require('../helpers/custom-validators').users | 3 | const customUsersValidators = require('../helpers/custom-validators').users |
4 | const modelUtils = require('./utils') | 4 | const modelUtils = require('./utils') |
5 | const peertubeCrypto = require('../helpers/peertube-crypto') | ||
5 | 6 | ||
6 | // --------------------------------------------------------------------------- | 7 | // --------------------------------------------------------------------------- |
7 | 8 | ||
@@ -20,27 +21,53 @@ UserSchema.path('username').required(customUsersValidators.isUserUsernameValid) | |||
20 | UserSchema.path('role').validate(customUsersValidators.isUserRoleValid) | 21 | UserSchema.path('role').validate(customUsersValidators.isUserRoleValid) |
21 | 22 | ||
22 | UserSchema.methods = { | 23 | UserSchema.methods = { |
24 | isPasswordMatch: isPasswordMatch, | ||
23 | toFormatedJSON: toFormatedJSON | 25 | toFormatedJSON: toFormatedJSON |
24 | } | 26 | } |
25 | 27 | ||
26 | UserSchema.statics = { | 28 | UserSchema.statics = { |
27 | countTotal: countTotal, | 29 | countTotal: countTotal, |
28 | getByUsernameAndPassword: getByUsernameAndPassword, | 30 | getByUsername: getByUsername, |
29 | listForApi: listForApi, | 31 | listForApi: listForApi, |
30 | loadById: loadById, | 32 | loadById: loadById, |
31 | loadByUsername: loadByUsername | 33 | loadByUsername: loadByUsername |
32 | } | 34 | } |
33 | 35 | ||
36 | UserSchema.pre('save', function (next) { | ||
37 | const user = this | ||
38 | |||
39 | peertubeCrypto.cryptPassword(this.password, function (err, hash) { | ||
40 | if (err) return next(err) | ||
41 | |||
42 | user.password = hash | ||
43 | |||
44 | return next() | ||
45 | }) | ||
46 | }) | ||
47 | |||
34 | mongoose.model('User', UserSchema) | 48 | mongoose.model('User', UserSchema) |
35 | 49 | ||
36 | // --------------------------------------------------------------------------- | 50 | // ------------------------------ METHODS ------------------------------ |
51 | |||
52 | function isPasswordMatch (password, callback) { | ||
53 | return peertubeCrypto.comparePassword(password, this.password, callback) | ||
54 | } | ||
55 | |||
56 | function toFormatedJSON () { | ||
57 | return { | ||
58 | id: this._id, | ||
59 | username: this.username, | ||
60 | role: this.role | ||
61 | } | ||
62 | } | ||
63 | // ------------------------------ STATICS ------------------------------ | ||
37 | 64 | ||
38 | function countTotal (callback) { | 65 | function countTotal (callback) { |
39 | return this.count(callback) | 66 | return this.count(callback) |
40 | } | 67 | } |
41 | 68 | ||
42 | function getByUsernameAndPassword (username, password) { | 69 | function getByUsername (username) { |
43 | return this.findOne({ username: username, password: password }) | 70 | return this.findOne({ username: username }) |
44 | } | 71 | } |
45 | 72 | ||
46 | function listForApi (start, count, sort, callback) { | 73 | function listForApi (start, count, sort, callback) { |
@@ -55,11 +82,3 @@ function loadById (id, callback) { | |||
55 | function loadByUsername (username, callback) { | 82 | function loadByUsername (username, callback) { |
56 | return this.findOne({ username: username }, callback) | 83 | return this.findOne({ username: username }, callback) |
57 | } | 84 | } |
58 | |||
59 | function toFormatedJSON () { | ||
60 | return { | ||
61 | id: this._id, | ||
62 | username: this.username, | ||
63 | role: this.role | ||
64 | } | ||
65 | } | ||