local network_core = require('network.core')
local context = require('mc.context')
local m_error_custom = require('messages.custom')
local IPMC_USER_PASSWORD_LEN <const> = 21
local ACCOUNT_MDB_PATH <const> = '/bmc/kepler/AccountService/Accounts'
local ACCOUNT_MDB_INTF <const> = 'bmc.kepler.AccountService.ManagerAccount'
local ACCOUNT_POLICY_MDB_INTF <const> = 'bmc.kepler.AccountService.AccountPolicy'
local LOCAL_ACCOUNT_POLICY_MDB_PATH <const> = '/bmc/kepler/AccountService/AccountPolicies/Local'
local OEM_ACCOUNT_POLICY_MDB_PATH <const> = '/bmc/kepler/AccountService/AccountPolicies/OemAccount'
local m = {}
local function is_repeated_substring(str)
local len = #str
for i = 2, len / 2 do
if len % i == 0 then
local sub = str:sub(1, i)
if sub:rep(len / i) == str then
return true
end
end
end
return false
end
function m.get_pwd(valid_path, path)
if valid_path and (type(path) ~= 'string' or #path == 0) then
return { -5, '' }
end
local status, password = libroutemapper_utils.get_line_without_echo('Password:')
if status ~= 0 or #password > 512 then
return { -1, password }
end
local pw_len = #password
for i = 1, pw_len do
if password:byte(i) < 0x20 or password:byte(i) > 0x7E then
return { -2, password }
end
end
local password_confirm
status, password_confirm = libroutemapper_utils.get_line_without_echo('Confirm password:')
if status ~= 0 or password ~= password_confirm then
return { -3, password }
end
if pw_len == 0 then
return { -5, password }
end
if is_repeated_substring(password) then
if
not mapper_interface.check_the_input_operation(
bus,
'WARNING: Using a password consisting of '
.. 'only repeated string may have many adverse effects, such as aa, ababab, and abcdabcd.\n'
.. 'Do you want to continue?[Y/N]:'
)
then
return { -4, password }
end
end
local res = {}
for i = 1, pw_len do
res[i] = password:byte(i)
end
return { 0, res }
end
function m.reset_pwd(need_reset, user_name)
if not need_reset then
return { 0, '' }
end
local hint = string.format('Reset user[%s]\'s Password:', user_name)
local status, password = libroutemapper_utils.get_line_without_echo(hint)
if status ~= 0 or #password >= IPMC_USER_PASSWORD_LEN then
return { -1, password }
end
local pw_len = #password
for i = 1, pw_len do
if password:byte(i) < 0x20 or password:byte(i) > 0x7E then
return { -2, password }
end
end
local password_confirm
status, password_confirm = libroutemapper_utils.get_line_without_echo('Confirm password:')
if status ~= 0 or password ~= password_confirm then
return { -3, password }
end
if is_repeated_substring(password) then
if
not mapper_interface.check_the_input_operation(
bus,
'WARNING: Using a password consisting of '
.. 'only repeated string may have many adverse effects, such as aa, ababab, and abcdabcd.\n'
.. 'Do you want to continue?[Y/N]:'
)
then
return { -4, password }
end
end
local res = {}
for i = 1, pw_len do
res[i] = password:byte(i)
end
return { 0, res }
end
local function is_have_user_mgmt(privileges)
for _, value in ipairs(privileges) do
if value == 'UserMgmt' then
return true
end
end
return false
end
local function get_account_visible_map()
local local_account_policy = mdb.get_object(bus, LOCAL_ACCOUNT_POLICY_MDB_PATH, ACCOUNT_POLICY_MDB_INTF)
local oem_account_policy = mdb.get_object(bus, OEM_ACCOUNT_POLICY_MDB_PATH, ACCOUNT_POLICY_MDB_INTF)
local account_visible_map = {}
account_visible_map['Local'] = local_account_policy.Visible
account_visible_map['OEM'] = oem_account_policy.Visible
return account_visible_map
end
function m.get_paths(Context)
local paths = {}
local tmp_paths = {}
local have_user_mgmt = is_have_user_mgmt(Context.Privilege)
local account_objs = mdb.get_sub_objects(bus, ACCOUNT_MDB_PATH, ACCOUNT_MDB_INTF)
local account_visible_map = get_account_visible_map()
if have_user_mgmt then
for path, account in pairs(account_objs) do
if not account_visible_map[account.AccountType] then
goto continue
end
local is_visible = account_visible_map[account.AccountType]
if is_visible then
tmp_paths[account.Id] = path
end
::continue::
end
else
for path, account in pairs(account_objs) do
if account.UserName == Context.UserName then
tmp_paths[account.Id] = path
end
end
end
for _, path in pairs(tmp_paths) do
paths[#paths + 1] = path
end
return paths
end
local function check_remote_file_path_valid(path, protocal)
local reverse_pos = string.find(string.reverse(path), '@')
if protocal ~= 'https:' and reverse_pos == nil then
return false
end
local remote_path_with_ip
if reverse_pos == nil then
remote_path_with_ip = string.sub(path, 8 + 1, #path)
else
remote_path_with_ip = string.sub(path, #path - reverse_pos + 2, #path)
end
local sub_pos = string.find(remote_path_with_ip, '/')
local ip = string.sub(remote_path_with_ip, 1, sub_pos - 1)
if network_core.verify_host_addr(ip) == -1 then
return false
end
return true
end
function m.check_path_valid(option, path)
if option ~= 'import' then
return true
end
if not path or #path == 0 then
return false
end
local URL_HEAD_TABLE = { 'https:', 'sftp:', 'nfs:', 'cifs:', 'scp:' }
for _, v in pairs(URL_HEAD_TABLE) do
if string.sub(path, 1, #v) == v then
return check_remote_file_path_valid(path, v)
end
end
return true
end
function m.is_permitted(ctx, path, permission)
if not ctx then
return true
end
local obj = mdb.get_object(bus, '/bmc/kepler/Managers/1/Security/File', 'bmc.kepler.Managers.Security.File')
local ok, ret = pcall(function()
return obj:IsPermitted(context.get_context(), path, permission)
end)
if not ok then
return false
end
return ret.Result
end
function m.get_role_id(ctx)
if not ctx then
return -1
end
local accounts_obj =
mdb.get_object(bus, '/bmc/kepler/AccountService/Accounts', 'bmc.kepler.AccountService.ManagerAccounts')
local ok, ret = pcall(function()
return accounts_obj:GetIdByUserName(context.get_context(), ctx.UserName)
end)
if not ok then
return -1
end
local account_obj = mdb.get_object(
bus,
'/bmc/kepler/AccountService/Accounts/' .. tostring(ret.AccountId),
'bmc.kepler.AccountService.ManagerAccount'
)
return account_obj.RoleId
end
function m.is_import_action_permitted(ctx, path, permission)
if m.get_role_id(ctx) == 4 or m.is_permitted(ctx, path, permission) then
return true
end
return false
end
function m.is_allow_operate(id, username, islog)
if not id or type(id) ~= 'number' then
if islog then
error(m_error_custom.UserNotExist(username))
end
return false
end
if id == 23 then
if islog then
error(m_error_custom.UserNotExist(username))
end
return false
end
return true
end
return m