From abf1d52fe70cae3c8dfff6e0c134a54c62f94e8a Mon Sep 17 00:00:00 2001 From: Nouhaila Idrissi Zouggari Date: Tue, 6 Aug 2024 11:53:38 +0200 Subject: [PATCH] MT#60641 Adapt random password generator to the new security standards In the last version mr12.5 we increased the security standards for the subscriber's password. Now it is mandatory to have: * password length min 12 chars * must have at least 3 digits * must have at least 3 lowercase letters * must have at least 3 uppercase letters * must have at least 3 special chars In this review we adapt the random password generator in the CSC. Change-Id: I8f257e34f7df8c99ef776ea9262fa18c32aef4da --- src/api/pbx-config.js | 4 -- src/api/pbx-groups.js | 9 ++-- src/api/pbx-seats.js | 9 ++-- src/api/subscriber.js | 37 +++++++++++++ src/components/form/CscInputPassword.vue | 67 ++++-------------------- src/store/user.js | 8 ++- 6 files changed, 65 insertions(+), 69 deletions(-) diff --git a/src/api/pbx-config.js b/src/api/pbx-config.js index 210c0526..218689a8 100644 --- a/src/api/pbx-config.js +++ b/src/api/pbx-config.js @@ -3,9 +3,6 @@ import _ from 'lodash' import { getSubscribers } from './subscriber' -import { - v4 -} from 'uuid' import { getList, get, @@ -14,7 +11,6 @@ import { httpApi } from './common' -export const createId = v4 export const PBX_CONFIG_ORDER_BY = 'create_timestamp' export const PBX_CONFIG_ORDER_DIRECTION = 'desc' diff --git a/src/api/pbx-groups.js b/src/api/pbx-groups.js index 72a4abf6..6a26b4a4 100644 --- a/src/api/pbx-groups.js +++ b/src/api/pbx-groups.js @@ -9,13 +9,13 @@ import { setPbxExtension, setPbxGroupMemberIds, setPbxHuntPolicy, setPbxHuntTimeout, setSubscriberNumbers, - setPbxHuntCancelMode + setPbxHuntCancelMode, + generateGeneralPassword } from './subscriber' import { getAllSoundSets, getPilot, getSoundSet, - createId, PBX_CONFIG_ORDER_BY, PBX_CONFIG_ORDER_DIRECTION, setSubscriberSoundSet @@ -114,13 +114,14 @@ export function getGroupList (options) { }) } -export function createGroup (group) { +export async function createGroup (group) { + const generatePassword = await generateGeneralPassword() return new Promise((resolve, reject) => { let subscriberId Promise.resolve().then(() => { return createSubscriber({ username: createUsername(group.name), - password: createId(), + password: generatePassword, is_pbx_group: true, display_name: group.name, pbx_extension: group.extension, diff --git a/src/api/pbx-seats.js b/src/api/pbx-seats.js index fa9e7e56..fc5b5861 100644 --- a/src/api/pbx-seats.js +++ b/src/api/pbx-seats.js @@ -20,14 +20,14 @@ import { setPreferenceAnnouncementToCallee, setPreferenceIgnoreCfWhenHunting, setPreferenceCstaClient, - setPreferenceCstaController + setPreferenceCstaController, + generateGeneralPassword } from './subscriber' import _ from 'lodash' import { getAllSoundSets, getPilot, getSoundSet, - createId, PBX_CONFIG_ORDER_BY, PBX_CONFIG_ORDER_DIRECTION, setSubscriberSoundSet, @@ -142,7 +142,8 @@ export function getSeatList (options) { }) } -export function createSeat (seat) { +export async function createSeat (seat) { + const generatePassword = await generateGeneralPassword() return new Promise((resolve, reject) => { let subscriberId Promise.resolve().then(() => { @@ -150,7 +151,7 @@ export function createSeat (seat) { username: seat.sipUsername.trim(), display_name: seat.displayName.trim(), webusername: seat.webUsername.trim(), - password: seat.sipPassword ? seat.sipPassword : createId(), + password: seat.sipPassword ? seat.sipPassword : generatePassword, webpassword: seat.webPassword.length > 0 ? seat.webPassword : null, is_pbx_group: false, pbx_extension: seat.extension, diff --git a/src/api/subscriber.js b/src/api/subscriber.js index 4548be80..efd5fc5c 100644 --- a/src/api/subscriber.js +++ b/src/api/subscriber.js @@ -20,6 +20,13 @@ import { assignNumbers } from './user' +const minValue = 3 +const generateSymbols = '!@#$%^&*()_+~`|}{[]:;?><,./-=' +const generateNumbers = '0123456789' +const generateLowercase = 'abcdefghijklmnopqrstuvwxyz' +const generateUppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +const generateLength = 12 + export function getPreferences (id) { return new Promise((resolve, reject) => { httpApi.get('api/subscriberpreferences/' + id).then((result) => { @@ -910,3 +917,33 @@ export function setCustomerPreference (customerId, customerValue, fieldName) { }) }) } + +export async function generateGeneralPassword () { + const getRandomValues = (buf) => crypto.getRandomValues(buf) + const getRandomInt = (max) => { + const randomBuffer = new Uint32Array(1) + getRandomValues(randomBuffer) + return Math.floor(randomBuffer[0] / (0xFFFFFFFF + 1) * max) + } + const getRandomChar = (charset) => charset[getRandomInt(charset.length)] + + const charGroups = [ + generateNumbers, + generateLowercase, + generateUppercase, + generateSymbols + ] + + let password = charGroups.flatMap(group => + Array.from({ length: minValue }, () => getRandomChar(group)) + ).join('') + + while (password.length < generateLength) { + const allChars = charGroups.join('') + password += getRandomChar(allChars) + } + + password = password.split('').sort(() => getRandomInt(2) - 0.5).join('') + + return password +} diff --git a/src/components/form/CscInputPassword.vue b/src/components/form/CscInputPassword.vue index 21658dab..c5ec119d 100644 --- a/src/components/form/CscInputPassword.vue +++ b/src/components/form/CscInputPassword.vue @@ -45,9 +45,10 @@ +