Ohm-Management - Projektarbeit B-ME
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

mongocr.js 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. 'use strict';
  2. var f = require('util').format,
  3. crypto = require('crypto'),
  4. Query = require('../connection/commands').Query,
  5. MongoError = require('../error').MongoError;
  6. var AuthSession = function(db, username, password) {
  7. this.db = db;
  8. this.username = username;
  9. this.password = password;
  10. };
  11. AuthSession.prototype.equal = function(session) {
  12. return (
  13. session.db === this.db &&
  14. session.username === this.username &&
  15. session.password === this.password
  16. );
  17. };
  18. /**
  19. * Creates a new MongoCR authentication mechanism
  20. * @class
  21. * @return {MongoCR} A cursor instance
  22. */
  23. var MongoCR = function(bson) {
  24. this.bson = bson;
  25. this.authStore = [];
  26. };
  27. // Add to store only if it does not exist
  28. var addAuthSession = function(authStore, session) {
  29. var found = false;
  30. for (var i = 0; i < authStore.length; i++) {
  31. if (authStore[i].equal(session)) {
  32. found = true;
  33. break;
  34. }
  35. }
  36. if (!found) authStore.push(session);
  37. };
  38. /**
  39. * Authenticate
  40. * @method
  41. * @param {{Server}|{ReplSet}|{Mongos}} server Topology the authentication method is being called on
  42. * @param {[]Connections} connections Connections to authenticate using this authenticator
  43. * @param {string} db Name of the database
  44. * @param {string} username Username
  45. * @param {string} password Password
  46. * @param {authResultCallback} callback The callback to return the result from the authentication
  47. * @return {object}
  48. */
  49. MongoCR.prototype.auth = function(server, connections, db, username, password, callback) {
  50. var self = this;
  51. // Total connections
  52. var count = connections.length;
  53. if (count === 0) return callback(null, null);
  54. // Valid connections
  55. var numberOfValidConnections = 0;
  56. var errorObject = null;
  57. // For each connection we need to authenticate
  58. while (connections.length > 0) {
  59. // Execute MongoCR
  60. var executeMongoCR = function(connection) {
  61. // Write the commmand on the connection
  62. server(
  63. connection,
  64. new Query(
  65. self.bson,
  66. f('%s.$cmd', db),
  67. {
  68. getnonce: 1
  69. },
  70. {
  71. numberToSkip: 0,
  72. numberToReturn: 1
  73. }
  74. ),
  75. function(err, r) {
  76. var nonce = null;
  77. var key = null;
  78. // Adjust the number of connections left
  79. // Get nonce
  80. if (err == null) {
  81. nonce = r.result.nonce;
  82. // Use node md5 generator
  83. var md5 = crypto.createHash('md5');
  84. // Generate keys used for authentication
  85. md5.update(username + ':mongo:' + password, 'utf8');
  86. var hash_password = md5.digest('hex');
  87. // Final key
  88. md5 = crypto.createHash('md5');
  89. md5.update(nonce + username + hash_password, 'utf8');
  90. key = md5.digest('hex');
  91. }
  92. // Execute command
  93. // Write the commmand on the connection
  94. server(
  95. connection,
  96. new Query(
  97. self.bson,
  98. f('%s.$cmd', db),
  99. {
  100. authenticate: 1,
  101. user: username,
  102. nonce: nonce,
  103. key: key
  104. },
  105. {
  106. numberToSkip: 0,
  107. numberToReturn: 1
  108. }
  109. ),
  110. function(err, r) {
  111. count = count - 1;
  112. // If we have an error
  113. if (err) {
  114. errorObject = err;
  115. } else if (r.result['$err']) {
  116. errorObject = r.result;
  117. } else if (r.result['errmsg']) {
  118. errorObject = r.result;
  119. } else {
  120. numberOfValidConnections = numberOfValidConnections + 1;
  121. }
  122. // We have authenticated all connections
  123. if (count === 0 && numberOfValidConnections > 0) {
  124. // Store the auth details
  125. addAuthSession(self.authStore, new AuthSession(db, username, password));
  126. // Return correct authentication
  127. callback(null, true);
  128. } else if (count === 0) {
  129. if (errorObject == null)
  130. errorObject = new MongoError(f('failed to authenticate using mongocr'));
  131. callback(errorObject, false);
  132. }
  133. }
  134. );
  135. }
  136. );
  137. };
  138. var _execute = function(_connection) {
  139. process.nextTick(function() {
  140. executeMongoCR(_connection);
  141. });
  142. };
  143. _execute(connections.shift());
  144. }
  145. };
  146. /**
  147. * Remove authStore credentials
  148. * @method
  149. * @param {string} db Name of database we are removing authStore details about
  150. * @return {object}
  151. */
  152. MongoCR.prototype.logout = function(dbName) {
  153. this.authStore = this.authStore.filter(function(x) {
  154. return x.db !== dbName;
  155. });
  156. };
  157. /**
  158. * Re authenticate pool
  159. * @method
  160. * @param {{Server}|{ReplSet}|{Mongos}} server Topology the authentication method is being called on
  161. * @param {[]Connections} connections Connections to authenticate using this authenticator
  162. * @param {authResultCallback} callback The callback to return the result from the authentication
  163. * @return {object}
  164. */
  165. MongoCR.prototype.reauthenticate = function(server, connections, callback) {
  166. var authStore = this.authStore.slice(0);
  167. var count = authStore.length;
  168. if (count === 0) return callback(null, null);
  169. // Iterate over all the auth details stored
  170. for (var i = 0; i < authStore.length; i++) {
  171. this.auth(
  172. server,
  173. connections,
  174. authStore[i].db,
  175. authStore[i].username,
  176. authStore[i].password,
  177. function(err) {
  178. count = count - 1;
  179. // Done re-authenticating
  180. if (count === 0) {
  181. callback(err, null);
  182. }
  183. }
  184. );
  185. }
  186. };
  187. /**
  188. * This is a result from a authentication strategy
  189. *
  190. * @callback authResultCallback
  191. * @param {error} error An error object. Set to null if no error present
  192. * @param {boolean} result The result of the authentication process
  193. */
  194. module.exports = MongoCR;