gssapi.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. 'use strict';
  2. const AuthProvider = require('./auth_provider').AuthProvider;
  3. const retrieveKerberos = require('../utils').retrieveKerberos;
  4. let kerberos;
  5. /**
  6. * Creates a new GSSAPI authentication mechanism
  7. * @class
  8. * @extends AuthProvider
  9. */
  10. class GSSAPI extends AuthProvider {
  11. /**
  12. * Implementation of authentication for a single connection
  13. * @override
  14. */
  15. _authenticateSingleConnection(sendAuthCommand, connection, credentials, callback) {
  16. const source = credentials.source;
  17. const username = credentials.username;
  18. const password = credentials.password;
  19. const mechanismProperties = credentials.mechanismProperties;
  20. const gssapiServiceName =
  21. mechanismProperties['gssapiservicename'] ||
  22. mechanismProperties['gssapiServiceName'] ||
  23. 'mongodb';
  24. GSSAPIInitialize(
  25. this,
  26. kerberos.processes.MongoAuthProcess,
  27. source,
  28. username,
  29. password,
  30. source,
  31. gssapiServiceName,
  32. sendAuthCommand,
  33. connection,
  34. mechanismProperties,
  35. callback
  36. );
  37. }
  38. /**
  39. * Authenticate
  40. * @override
  41. * @method
  42. */
  43. auth(sendAuthCommand, connections, credentials, callback) {
  44. if (kerberos == null) {
  45. try {
  46. kerberos = retrieveKerberos();
  47. } catch (e) {
  48. return callback(e, null);
  49. }
  50. }
  51. super.auth(sendAuthCommand, connections, credentials, callback);
  52. }
  53. }
  54. //
  55. // Initialize step
  56. var GSSAPIInitialize = function(
  57. self,
  58. MongoAuthProcess,
  59. db,
  60. username,
  61. password,
  62. authdb,
  63. gssapiServiceName,
  64. sendAuthCommand,
  65. connection,
  66. options,
  67. callback
  68. ) {
  69. // Create authenticator
  70. var mongo_auth_process = new MongoAuthProcess(
  71. connection.host,
  72. connection.port,
  73. gssapiServiceName,
  74. options
  75. );
  76. // Perform initialization
  77. mongo_auth_process.init(username, password, function(err) {
  78. if (err) return callback(err, false);
  79. // Perform the first step
  80. mongo_auth_process.transition('', function(err, payload) {
  81. if (err) return callback(err, false);
  82. // Call the next db step
  83. MongoDBGSSAPIFirstStep(
  84. self,
  85. mongo_auth_process,
  86. payload,
  87. db,
  88. username,
  89. password,
  90. authdb,
  91. sendAuthCommand,
  92. connection,
  93. callback
  94. );
  95. });
  96. });
  97. };
  98. //
  99. // Perform first step against mongodb
  100. var MongoDBGSSAPIFirstStep = function(
  101. self,
  102. mongo_auth_process,
  103. payload,
  104. db,
  105. username,
  106. password,
  107. authdb,
  108. sendAuthCommand,
  109. connection,
  110. callback
  111. ) {
  112. // Build the sasl start command
  113. var command = {
  114. saslStart: 1,
  115. mechanism: 'GSSAPI',
  116. payload: payload,
  117. autoAuthorize: 1
  118. };
  119. // Write the commmand on the connection
  120. sendAuthCommand(connection, '$external.$cmd', command, (err, doc) => {
  121. if (err) return callback(err, false);
  122. // Execute mongodb transition
  123. mongo_auth_process.transition(doc.payload, function(err, payload) {
  124. if (err) return callback(err, false);
  125. // MongoDB API Second Step
  126. MongoDBGSSAPISecondStep(
  127. self,
  128. mongo_auth_process,
  129. payload,
  130. doc,
  131. db,
  132. username,
  133. password,
  134. authdb,
  135. sendAuthCommand,
  136. connection,
  137. callback
  138. );
  139. });
  140. });
  141. };
  142. //
  143. // Perform first step against mongodb
  144. var MongoDBGSSAPISecondStep = function(
  145. self,
  146. mongo_auth_process,
  147. payload,
  148. doc,
  149. db,
  150. username,
  151. password,
  152. authdb,
  153. sendAuthCommand,
  154. connection,
  155. callback
  156. ) {
  157. // Build Authentication command to send to MongoDB
  158. var command = {
  159. saslContinue: 1,
  160. conversationId: doc.conversationId,
  161. payload: payload
  162. };
  163. // Execute the command
  164. // Write the commmand on the connection
  165. sendAuthCommand(connection, '$external.$cmd', command, (err, doc) => {
  166. if (err) return callback(err, false);
  167. // Call next transition for kerberos
  168. mongo_auth_process.transition(doc.payload, function(err, payload) {
  169. if (err) return callback(err, false);
  170. // Call the last and third step
  171. MongoDBGSSAPIThirdStep(
  172. self,
  173. mongo_auth_process,
  174. payload,
  175. doc,
  176. db,
  177. username,
  178. password,
  179. authdb,
  180. sendAuthCommand,
  181. connection,
  182. callback
  183. );
  184. });
  185. });
  186. };
  187. var MongoDBGSSAPIThirdStep = function(
  188. self,
  189. mongo_auth_process,
  190. payload,
  191. doc,
  192. db,
  193. username,
  194. password,
  195. authdb,
  196. sendAuthCommand,
  197. connection,
  198. callback
  199. ) {
  200. // Build final command
  201. var command = {
  202. saslContinue: 1,
  203. conversationId: doc.conversationId,
  204. payload: payload
  205. };
  206. // Execute the command
  207. sendAuthCommand(connection, '$external.$cmd', command, (err, r) => {
  208. if (err) return callback(err, false);
  209. mongo_auth_process.transition(null, function(err) {
  210. if (err) return callback(err, null);
  211. callback(null, r);
  212. });
  213. });
  214. };
  215. /**
  216. * This is a result from a authentication strategy
  217. *
  218. * @callback authResultCallback
  219. * @param {error} error An error object. Set to null if no error present
  220. * @param {boolean} result The result of the authentication process
  221. */
  222. module.exports = GSSAPI;