'use strict';

/*global Promise*/
var PromiseA = Promise;
var crypto = require('crypto');
var util = require('util');
var readFile = util.promisify(require('fs').readFile);
var exec = require('child_process').exec;

function sshAllowsPassword(user) {
  // SSH on Windows is a thing now (beta 2015, standard 2018)
  // https://stackoverflow.com/questions/313111/is-there-a-dev-null-on-windows
  var nullfile = '/dev/null';
  if (/^win/i.test(process.platform)) {
    nullfile = 'NUL';
  }
  var args = [
    'ssh', '-v', '-n'
  , '-o', 'Batchmode=yes'
  , '-o', 'StrictHostKeyChecking=no'
  , '-o', 'UserKnownHostsFile=' + nullfile
  , user + '@localhost'
  , '| true'
  ];
  return new PromiseA(function (resolve) {
    // not using promisify because all 3 arguments convey information
    exec(args.join(' '), function (err, stdout, stderr) {
      stdout = (stdout||'').toString('utf8');
      stderr = (stderr||'').toString('utf8');
      if (/\bpassword\b/.test(stdout) || /\bpassword\b/.test(stderr)) {
        resolve('yes');
        return;
      }
      if (/\bAuthentications\b/.test(stdout) || /\bAuthentications\b/.test(stderr)) {
        resolve('no');
        return;
      }
      resolve('maybe');
    });
  });
}

module.exports.checkSecurity = function () {
  var conf = {};
  var noRootPasswordRe = /(?:^|[\r\n]+)\s*PermitRootLogin\s+(prohibit-password|without-password|no)\s*/i;
  var noPasswordRe = /(?:^|[\r\n]+)\s*PasswordAuthentication\s+(no)\s*/i;
  var sshdConf = '/etc/ssh/sshd_config';
  if (/^win/i.test(process.platform)) {
    // TODO use %PROGRAMDATA%\ssh\sshd_config
    sshdConf = 'C:\\ProgramData\\ssh\\sshd_config';
  }
  return readFile(sshdConf, null).then(function (sshd) {
    sshd = sshd.toString('utf8');
    var match;
    match = sshd.match(noRootPasswordRe);
    conf.permit_root_login = match ? match[1] : 'yes';
    match = sshd.match(noPasswordRe);
    conf.password_authentication = match ? match[1] : 'yes';
  }).catch(function () {
    // ignore error as that might not be the correct sshd_config location
  }).then(function () {
    var doesntExist = crypto.randomBytes(16).toString('hex');
    return sshAllowsPassword(doesntExist).then(function (maybe) {
      conf.requests_password = maybe;
    });
  }).then(function () {
    return conf;
  });
};

if (require.main === module) {
  module.exports.checkSecurity().then(function (conf) {
    console.log(conf);
    return conf;
  });
}