123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- const PluginAuth = require('./plugin-auth');
- const fs = require('fs');
- const crypto = require('crypto');
- const Errors = require('../../../misc/errors');
- /**
- * Use Sha256 authentication
- */
- class Sha256PasswordAuth extends PluginAuth {
- constructor(packSeq, compressPackSeq, pluginData, resolve, reject, multiAuthResolver) {
- super(resolve, reject, multiAuthResolver);
- this.pluginData = pluginData;
- this.sequenceNo = packSeq;
- this.counter = 0;
- this.initialState = true;
- }
- start(out, opts, info) {
- this.exchange(this.pluginData, out, opts, info);
- this.onPacketReceive = this.response;
- }
- exchange(buffer, out, opts, info) {
- if (this.initialState) {
- if (!opts.password) {
- out.startPacket(this);
- out.writeEmptyPacket(true);
- return;
- } else if (opts.ssl) {
- // using SSL, so sending password in clear
- out.startPacket(this);
- if (opts.password) {
- out.writeString(opts.password);
- }
- out.writeInt8(0);
- out.flushBuffer(true);
- return;
- } else {
- // retrieve public key from configuration or from server
- if (opts.rsaPublicKey) {
- try {
- let key = opts.rsaPublicKey;
- if (!key.includes('-----BEGIN')) {
- // rsaPublicKey contain path
- key = fs.readFileSync(key, 'utf8');
- }
- this.publicKey = Sha256PasswordAuth.retreivePublicKey(key);
- } catch (err) {
- return this.throwError(err, info);
- }
- } else {
- if (!opts.allowPublicKeyRetrieval) {
- return this.throwError(
- Errors.createError(
- 'RSA public key is not available client side. Either set option `rsaPublicKey` to indicate' +
- ' public key path, or allow public key retrieval with option `allowPublicKeyRetrieval`',
- true,
- info,
- '08S01',
- Errors.ER_CANNOT_RETRIEVE_RSA_KEY
- ),
- info
- );
- }
- this.initialState = false;
- // ask public Key Retrieval
- out.startPacket(this);
- out.writeInt8(0x01);
- out.flushBuffer(true);
- return;
- }
- }
- // send Sha256Password Packet
- Sha256PasswordAuth.sendSha256PwdPacket(
- this,
- this.pluginData,
- this.publicKey,
- opts.password,
- out
- );
- } else {
- // has request public key
- this.publicKey = Sha256PasswordAuth.retreivePublicKey(buffer.toString('utf8', 1));
- Sha256PasswordAuth.sendSha256PwdPacket(
- this,
- this.pluginData,
- this.publicKey,
- opts.password,
- out
- );
- }
- }
- static retreivePublicKey(key) {
- return key.replace('(-+BEGIN PUBLIC KEY-+\\r?\\n|\\n?-+END PUBLIC KEY-+\\r?\\n?)', '');
- }
- static sendSha256PwdPacket(cmd, pluginData, publicKey, password, out) {
- const truncatedSeed = pluginData.slice(0, pluginData.length - 1);
- out.startPacket(cmd);
- const enc = Sha256PasswordAuth.encrypt(truncatedSeed, password, publicKey);
- out.writeBuffer(enc, 0, enc.length);
- out.flushBuffer(cmd);
- }
- // encrypt password with public key
- static encrypt(seed, password, publicKey) {
- const nullFinishedPwd = Buffer.from(password + '\0');
- const xorBytes = Buffer.allocUnsafe(nullFinishedPwd.length);
- const seedLength = seed.length;
- for (let i = 0; i < xorBytes.length; i++) {
- xorBytes[i] = nullFinishedPwd[i] ^ seed[i % seedLength];
- }
- return crypto.publicEncrypt(
- { key: publicKey, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING },
- xorBytes
- );
- }
- response(packet, out, opts, info) {
- const marker = packet.peek();
- switch (marker) {
- //*********************************************************************************************************
- //* OK_Packet and Err_Packet ending packet
- //*********************************************************************************************************
- case 0x00:
- case 0xff:
- this.emit('send_end');
- return this.successSend(packet, out, opts, info);
- default:
- let promptData = packet.readBufferRemaining();
- this.exchange(promptData, out, opts, info);
- this.onPacketReceive = this.response;
- }
- }
- }
- module.exports = Sha256PasswordAuth;
|