Skip to content

Commit

Permalink
SHARD-892: Add password upper limit (#43)
Browse files Browse the repository at this point in the history
* feat: limit password length

* feat: add description

* fix: password authentication
  • Loading branch information
Glitch18 authored Dec 9, 2024
1 parent 7487287 commit 189ac32
Showing 1 changed file with 41 additions and 22 deletions.
63 changes: 41 additions & 22 deletions src/gui-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,27 @@ import path = require('path');
import {timingSafeEqual} from 'crypto';
import {Pm2ProcessStatus, statusFromPM2} from './pm2';
import merge from 'deepmerge';
import {defaultGuiConfig, guiConfigType, guiConfigSchema} from './config/default-gui-config';
import {
defaultGuiConfig,
guiConfigType,
guiConfigSchema,
} from './config/default-gui-config';
import fs from 'fs';
import * as yaml from 'js-yaml';
import * as cryptoShardus from '@shardus/crypto-utils';
import {getInstalledGuiVersion} from './utils/project-data';
import {File} from './utils'
import {File} from './utils';
import crypto from 'crypto';
import Ajv from "ajv"
import Ajv from 'ajv';
import argon2id from 'argon2';

let config = defaultGuiConfig;

const validateGuiConfig = new Ajv().compile(guiConfigSchema)
const validateGuiConfig = new Ajv().compile(guiConfigSchema);

cryptoShardus.init('64f152869ca2d473e4ba64ab53f49ccdb2edae22da192c126850970e788af347');
cryptoShardus.init(
'64f152869ca2d473e4ba64ab53f49ccdb2edae22da192c126850970e788af347'
);

function isNumber(n: string) {
const parsedN = parseInt(n);
Expand All @@ -28,23 +34,29 @@ function isNumber(n: string) {
function validPassword(password: string) {
return (
password.length >= 8 &&
password.length <= 128 &&
/[A-Z]/.test(password) &&
/[a-z]/.test(password) &&
/[0-9]/.test(password) &&
/[!@#$%^&*()_+*$]/.test(password)
);
}

const guiConfigPath = path.join(__dirname, `../${File.GUI_CONFIG}`)
if (fs.existsSync(guiConfigPath)) { // eslint-disable-line security/detect-non-literal-fs-filename
const guiConfigPath = path.join(__dirname, `../${File.GUI_CONFIG}`);
if (fs.existsSync(guiConfigPath)) {
// eslint-disable-line security/detect-non-literal-fs-filename
// eslint-disable-next-line security/detect-non-literal-fs-filename
const fileConfig = JSON.parse(fs.readFileSync(guiConfigPath).toString())
const fileConfig = JSON.parse(fs.readFileSync(guiConfigPath).toString());
if (validateGuiConfig(fileConfig)) {
config = merge(config, fileConfig as guiConfigType, {arrayMerge: (target, source) => source})
config = merge(config, fileConfig as guiConfigType, {
arrayMerge: (target, source) => source,
});
// `as guiConfigType` above is valid because validateGuiConfig() passed
} else {
console.warn(`warning: config has been ignored due to invalid JSON schema:`)
console.warn(`${guiConfigPath}`)
console.warn(
`warning: config has been ignored due to invalid JSON schema:`
);
console.warn(`${guiConfigPath}`);
}
}

Expand Down Expand Up @@ -111,12 +123,12 @@ export function registerGuiCommands(program: Command) {
.description('Set the GUI server port')
.action(port => {
if (!isNumber(port)) {
console.error("Port is not a number");
console.error('Port is not a number');
return;
}
port = parseInt(port);
if(port < 1024) {
console.error("Port is reserved");
if (port < 1024) {
console.error('Port is reserved');
return;
}
config.gui.port = parseInt(port);
Expand All @@ -135,7 +147,9 @@ export function registerGuiCommands(program: Command) {
setCommand
.command('password')
.arguments('<password>')
.description('Set the GUI server password, requirements: min 8 characters, at least 1 lower case letter, at least 1 upper case letter, at least 1 number, at least 1 special character !@#$%^&*()_+*$')
.description(
'Set the GUI server password, requirements: min 8 characters, max 128 characters, at least 1 lower case letter, at least 1 upper case letter, at least 1 number, at least 1 special character !@#$%^&*()_+*$'
)
.option('-h', 'Changes how the password is hashed. For internal use only')
.action(async (password, options) => {
if (!options.h) {
Expand Down Expand Up @@ -163,14 +177,19 @@ export function registerGuiCommands(program: Command) {
.command('login')
.arguments('<password>')
.description('verify GUI password')
.action(password => {
if (
!timingSafeEqual(Buffer.from(password), Buffer.from(config.gui.pass))
) {
console.log(yaml.dump({login: 'unauthorized'}));
return;
.action(async password => {
try {
// Verify the password with saved hash
const isValid = await argon2id.verify(config.gui.pass, password);
if (!isValid) {
console.log(yaml.dump({login: 'unauthorized'}));
return;
}
console.log(yaml.dump({login: 'authorized'}));
} catch (err) {
console.error('Error during password verification:', err);
console.log(yaml.dump({login: 'unauthorized'})); // Fail-safe unauthorized output
}
console.log(yaml.dump({login: 'authorized'}));
});

function startGui() {
Expand Down

0 comments on commit 189ac32

Please sign in to comment.