-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--         http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

-- 外部依赖
local log = require 'mc.logging'
local mdb_service = require 'mc.mdb.mdb_service'
local cjson = require 'cjson'

-- SSL证书路径
local SSL_PATH<const> = '/bmc/kepler/Managers/1/NetworkProtocol/HTTPS/Certificates/1'
-- CA证书路径
local CA_PATH<const> = '/bmc/kepler/Managers/1/Certificates/%d'

local m = {}

function m.get_ssl_cert_info(destination, subject_destination)
    local ok, rsp = pcall(mdb_service.is_valid_path, bus, SSL_PATH)
    if not ok or not rsp.Result then
        return {}
    end
    local client_cert_info = destination
    client_cert_info.AlternativeNames = subject_destination.AlternativeNames
    return { ClientCert = client_cert_info }
end

function m.is_valid_cert(id)
    local id_number = tonumber(id)
    if not id_number then
        log:error('the id(%s) of cert is invalid', id)
        return false
    end
    if id_number < 1 or id_number > 32 then
        log:error('the id(%u) of cert is invalid', id_number)
        return false
    end
    local path = string.format(CA_PATH, id_number)
    local ok, rsp = pcall(mdb_service.is_valid_path, bus, path)
    if not ok or not rsp.Result then
        log:error('the id(%u) of cert is invalid', id_number)
        return false
    end
    return true
end

local function drop_cert_table_keys(cert_info)
    if not cert_info then
        return nil
    end
    return {
        Issuer = cert_info.Issuer,
        Subject = cert_info.Subject,
        ValidNotBefore = cert_info.ValidNotBefore,
        ValidNotAfter = cert_info.ValidNotAfter,
        SerialNumber = cert_info.SerialNumber
    }
end

function m.get_cert_chain_info(cert_info, subject_destination)
    local cert_infos = cjson.decode(cert_info)
    local server_info = drop_cert_table_keys(cert_infos['ServerCert'])
    local root_info = drop_cert_table_keys(cert_infos['RootCert'])
    local intermediate_info = {}
    if cert_infos['IntermediateCert'] then
        for idx, c_info in ipairs(cert_infos['IntermediateCert']) do
            intermediate_info[idx] = drop_cert_table_keys(c_info)
        end
    end
    local server_cert_info = server_info
    server_cert_info.AlternativeNames = subject_destination.AlternativeNames
    return {ServerCert = server_cert_info, IntermediateCert = intermediate_info, RootCert = root_info}
end

return m
