client-handshake-response.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. 'use strict';
  2. const Capabilities = require('../../const/capabilities');
  3. const Iconv = require('iconv-lite');
  4. const NativePasswordAuth = require('./auth/native-password-auth');
  5. const Ed25519PasswordAuth = require('./auth/ed25519-password-auth');
  6. const driverVersion = require('../../../package.json').version;
  7. const os = require('os');
  8. /**
  9. * Send Handshake response packet
  10. * see https://mariadb.com/kb/en/library/1-connecting-connecting/#handshake-response-packet
  11. *
  12. * @param cmd current handshake command
  13. * @param out output writer
  14. * @param opts connection options
  15. * @param pluginName plugin name
  16. * @param info connection information
  17. */
  18. module.exports.send = function send(cmd, out, opts, pluginName, info) {
  19. out.startPacket(cmd);
  20. info.defaultPluginName = pluginName;
  21. const pwd = Array.isArray(opts.password) ? opts.password[0] : opts.password;
  22. let authToken;
  23. let authPlugin;
  24. switch (pluginName) {
  25. case 'client_ed25519':
  26. authToken = Ed25519PasswordAuth.encryptPassword(pwd, info.seed);
  27. authPlugin = 'client_ed25519';
  28. break;
  29. case 'mysql_clear_password':
  30. authToken = Buffer.from(pwd);
  31. authPlugin = 'mysql_clear_password';
  32. break;
  33. default:
  34. authToken = NativePasswordAuth.encryptPassword(pwd, info.seed, 'sha1');
  35. authPlugin = 'mysql_native_password';
  36. break;
  37. }
  38. out.writeInt32(Number(info.clientCapabilities & BigInt(0xffffffff)));
  39. out.writeInt32(1024 * 1024 * 1024); // max packet size
  40. out.writeInt8(opts.collation.index);
  41. for (let i = 0; i < 19; i++) {
  42. out.writeInt8(0);
  43. }
  44. out.writeInt32(Number(info.clientCapabilities >> BigInt(32)));
  45. //null encoded user
  46. out.writeString(opts.user || '');
  47. out.writeInt8(0);
  48. if (info.serverCapabilities & Capabilities.PLUGIN_AUTH_LENENC_CLIENT_DATA) {
  49. out.writeLengthCoded(authToken.length);
  50. out.writeBuffer(authToken, 0, authToken.length);
  51. } else if (info.serverCapabilities & Capabilities.SECURE_CONNECTION) {
  52. out.writeInt8(authToken.length);
  53. out.writeBuffer(authToken, 0, authToken.length);
  54. } else {
  55. out.writeBuffer(authToken, 0, authToken.length);
  56. out.writeInt8(0);
  57. }
  58. if (info.clientCapabilities & Capabilities.CONNECT_WITH_DB) {
  59. out.writeString(opts.database);
  60. out.writeInt8(0);
  61. info.database = opts.database;
  62. }
  63. if (info.clientCapabilities & Capabilities.PLUGIN_AUTH) {
  64. out.writeString(authPlugin);
  65. out.writeInt8(0);
  66. }
  67. if (info.clientCapabilities & Capabilities.CONNECT_ATTRS) {
  68. out.writeInt8(0xfc);
  69. let initPos = out.pos; //save position, assuming connection attributes length will be less than 2 bytes length
  70. out.writeInt16(0);
  71. const encoding = opts.collation.charset;
  72. writeParam(out, '_client_name', encoding);
  73. writeParam(out, 'MariaDB connector/Node', encoding);
  74. writeParam(out, '_client_version', encoding);
  75. writeParam(out, driverVersion, encoding);
  76. const address = cmd.getSocket().address().address;
  77. if (address) {
  78. writeParam(out, '_server_host', encoding);
  79. writeParam(out, address, encoding);
  80. }
  81. writeParam(out, '_os', encoding);
  82. writeParam(out, process.platform, encoding);
  83. writeParam(out, '_client_host', encoding);
  84. writeParam(out, os.hostname(), encoding);
  85. writeParam(out, '_node_version', encoding);
  86. writeParam(out, process.versions.node, encoding);
  87. if (opts.connectAttributes !== true) {
  88. let attrNames = Object.keys(opts.connectAttributes);
  89. for (let k = 0; k < attrNames.length; ++k) {
  90. writeParam(out, attrNames[k], encoding);
  91. writeParam(out, opts.connectAttributes[attrNames[k]], encoding);
  92. }
  93. }
  94. //write end size
  95. out.writeInt16AtPos(initPos);
  96. }
  97. out.flushBuffer(true);
  98. };
  99. function writeParam(out, val, encoding) {
  100. let param = Buffer.isEncoding(encoding)
  101. ? Buffer.from(val, encoding)
  102. : Iconv.encode(val, encoding);
  103. out.writeLengthCoded(param.length);
  104. out.writeBuffer(param, 0, param.length);
  105. }