Handshake.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. var Sequence = require('./Sequence');
  2. var Util = require('util');
  3. var Packets = require('../packets');
  4. var Auth = require('../Auth');
  5. var ClientConstants = require('../constants/client');
  6. module.exports = Handshake;
  7. Util.inherits(Handshake, Sequence);
  8. function Handshake(options, callback) {
  9. Sequence.call(this, options, callback);
  10. options = options || {};
  11. this._config = options.config;
  12. this._handshakeInitializationPacket = null;
  13. }
  14. Handshake.prototype.determinePacket = function determinePacket(firstByte, parser) {
  15. if (firstByte === 0xff) {
  16. return Packets.ErrorPacket;
  17. }
  18. if (!this._handshakeInitializationPacket) {
  19. return Packets.HandshakeInitializationPacket;
  20. }
  21. if (firstByte === 0xfe) {
  22. return (parser.packetLength() === 1)
  23. ? Packets.UseOldPasswordPacket
  24. : Packets.AuthSwitchRequestPacket;
  25. }
  26. return undefined;
  27. };
  28. Handshake.prototype['AuthSwitchRequestPacket'] = function (packet) {
  29. if (packet.authMethodName === 'mysql_native_password') {
  30. var challenge = packet.authMethodData.slice(0, 20);
  31. this.emit('packet', new Packets.AuthSwitchResponsePacket({
  32. data: Auth.token(this._config.password, challenge)
  33. }));
  34. } else {
  35. var err = new Error(
  36. 'MySQL is requesting the ' + packet.authMethodName + ' authentication method, which is not supported.'
  37. );
  38. err.code = 'UNSUPPORTED_AUTH_METHOD';
  39. err.fatal = true;
  40. this.end(err);
  41. }
  42. };
  43. Handshake.prototype['HandshakeInitializationPacket'] = function(packet) {
  44. this._handshakeInitializationPacket = packet;
  45. this._config.protocol41 = packet.protocol41;
  46. var serverSSLSupport = packet.serverCapabilities1 & ClientConstants.CLIENT_SSL;
  47. if (this._config.ssl) {
  48. if (!serverSSLSupport) {
  49. var err = new Error('Server does not support secure connection');
  50. err.code = 'HANDSHAKE_NO_SSL_SUPPORT';
  51. err.fatal = true;
  52. this.end(err);
  53. return;
  54. }
  55. this._config.clientFlags |= ClientConstants.CLIENT_SSL;
  56. this.emit('packet', new Packets.SSLRequestPacket({
  57. clientFlags : this._config.clientFlags,
  58. maxPacketSize : this._config.maxPacketSize,
  59. charsetNumber : this._config.charsetNumber
  60. }));
  61. this.emit('start-tls');
  62. } else {
  63. this._sendCredentials();
  64. }
  65. };
  66. Handshake.prototype._tlsUpgradeCompleteHandler = function() {
  67. this._sendCredentials();
  68. };
  69. Handshake.prototype._sendCredentials = function() {
  70. var packet = this._handshakeInitializationPacket;
  71. this.emit('packet', new Packets.ClientAuthenticationPacket({
  72. clientFlags : this._config.clientFlags,
  73. maxPacketSize : this._config.maxPacketSize,
  74. charsetNumber : this._config.charsetNumber,
  75. user : this._config.user,
  76. database : this._config.database,
  77. protocol41 : packet.protocol41,
  78. scrambleBuff : (packet.protocol41)
  79. ? Auth.token(this._config.password, packet.scrambleBuff())
  80. : Auth.scramble323(packet.scrambleBuff(), this._config.password)
  81. }));
  82. };
  83. Handshake.prototype['UseOldPasswordPacket'] = function() {
  84. if (!this._config.insecureAuth) {
  85. var err = new Error(
  86. 'MySQL server is requesting the old and insecure pre-4.1 auth mechanism. ' +
  87. 'Upgrade the user password or use the {insecureAuth: true} option.'
  88. );
  89. err.code = 'HANDSHAKE_INSECURE_AUTH';
  90. err.fatal = true;
  91. this.end(err);
  92. return;
  93. }
  94. this.emit('packet', new Packets.OldPasswordPacket({
  95. scrambleBuff: Auth.scramble323(this._handshakeInitializationPacket.scrambleBuff(), this._config.password)
  96. }));
  97. };
  98. Handshake.prototype['ErrorPacket'] = function(packet) {
  99. var err = this._packetToError(packet, true);
  100. err.fatal = true;
  101. this.end(err);
  102. };