首页 文章

代码是否可以在Ada中受到恶意攻击者的保护?

提问于
浏览
3

我是一个相当新的Ada程序员 . 我读过Barnes的书(我可能会补充两次)甚至设法在Ada写一个公平的终端程序 . 我的主要语言是C语言 .

我目前想知道是否有办法在Ada中“保护”子程序调用,也许在Ada 2012中(我基本上什么都不知道) . 让我解释一下我的意思(尽管用C语言) .

假设您有一个类 Secret ,如下所示:

class Secret
{
    private:
    int secret_int;

    public:
    Set_Secret_Value( int i );
}

现在这是常见的东西,不要暴露secret_int,只能通过访问函数来操纵它 . 但是,问题是任何有权访问Secret类型对象的人都可以操纵该值,无论该特定代码段是否应该这样做 . 因此,恶意改变secret_int的危险已经减少到任何人通过允许的函数改变secret_int,即使它发生在不应该操纵它的代码部分 .

为了解决这个问题,我想出了以下结构

class Secret
{
    friend class Secret_Interface;

    private:
    int secret_int;
    Set_Secret_Value( int i );
    Super_Secret_Function();
};

class Secret_Interface
{
    friend class Client;
    private:

    static Set_Secret_Value( Secret &rc_secret_object, int i )
    {
         rc_secret_object.Set_Secret( i );
    }
};


class Client
{
     Some_Function()
     {
         ...
         Secret_Interface::Set_Secret_Value( c_object, some-value );
         ...
     }
}

现在,类 Secret_Interface 可以确定哪些其他类可以使用它的私有函数,并通过这样做间接地实现暴露于 Secret_Interface 的类Secret的函数 . 这样,类Secret仍然具有私有函数,这些函数不能被类外的任何人调用,例如函数 Super_Secret_Function() .

好吧,我想知道在Ada中是否有任何类型的东西是可能的 . 基本上我的愿望是能够说:

Code A may only be executed by code B but not by anybody else

谢谢你的帮助 .

编辑:我在这里添加一个图表,其程序结构就像我想到的那样,这表明我的意思是数据结构在软件的广泛区域内的传输,记录的定义,创建和使用应该在代码中发生其他部分无法解释
Flow Of One Data element

4 回答

  • 2

    您可以使用子包来执行此操作:

    package Hidden is
    
    private
    
       A : Integer;
       B : Integer;
    
    end Hidden;
    

    然后

    package Hidden.Client_A_View is
    
       function Get_A return Integer;
       procedure Set_A (To : Integer);
    
    end Hidden.Client_A_View;
    

    然后, Client_A 可以写

    with Hidden.Client_A_View;
    procedure Client_A is
       Tmp : Integer;
    begin
       Tmp := Hidden.Client_A_View.Get_A;
       Hidden.Client_A_View.Set_A (Tmp + 1);
    end Client_A;
    
  • 6

    我认为关键是要意识到,与C和其他语言不同,Ada的主要顶级单位是 package ,可见性控制(即公共与私有)是基于每个包,而不是每个类型(或每个 class ) . 我正确地说,但希望事情将在下面解释 .

    C中 friend 的主要目的之一是,您可以编写两个(或更多)密切相关的 class ,它们都参与实现一个概念 . 在这种情况下,有意义的是,一个类中的代码能够更直接地访问另一个类中的代码,因为它们在一起工作 . 我假设在你的C例子中, SecretClient 有这种亲密的关系 . 如果我正确理解C,那么它们都必须在同一个源文件中定义;如果你说 friend class Client ,那么 Client 类必须稍后在相同的源文件中定义(并且之前不能定义它,因为此时 SecretSecret_Interface 中的方法尚未声明) .

    在Ada中,您只需在同一个包中定义类型即可 .

    package P is
    
        type Secret is tagged private;
        type Client is tagged private;
    
        -- define public operations for both types 
    
    private
    
        type Secret is tagged record ... end record;
        type Client is tagged record ... end record;
    
        -- define private operations for either or both types
    
    end P;
    

    现在, P 的主体将包含两种类型的公共和私有操作的实际代码 . Ppackage body 中的所有代码都可以访问 Pprivate 部分中定义的内容,无论它们在哪种类型上运行 . 事实上,所有代码都可以访问这两种类型的完整定义 . 这意味着在 Client 上运行的过程可以调用在 Secret 上运行的私有操作,实际上它可以直接读写 Secret 的记录组件 . (反之亦然 . )对于习惯于大多数其他OOP语言使用的范例的程序员来说,这看起来很奇怪,但它在Ada中运行良好 . (事实上,如果除了 Client 的实现之外不需要 Secret 可以访问其他任何内容,则可以在 Pprivate 部分或 package body 中定义类型及其操作 . )这种安排不违反OOP背后的原理(封装,信息隐藏),只要这两种类型真正实现了两个相干概念的实现 .

    如果那不是您想要的,即 SecretClient 是否正在尝试实施 .

    MORE THOUGHTS: 在查看图表之后,我认为您尝试解决问题的方式是劣质设计 - 如果您愿意的话,这是一种反模式 . 当你写一个"module"(无论这意味着什么 - 一个类或包,或在某些情况下两个或更密切相关的类或包相互协作),该模块定义了其他模块如何使用它 - 它在其对象上提供的公共操作以及这些操作的作用 .

    但是根据 Contract ,模块(我们称之为M1)应该以相同的方式工作,无论其他模块调用它,以及如何 . M1将获得一系列“消息”,指示其执行某些任务或返回某些信息; M1不应该关心这些消息的来源 . 特别是,M1不应该对使用它的客户端的结构做出决定 . 通过M1法令“只能从包ABC中调用程序XYZ”,M1对使用它的客户施加了结构要求 . 我相信这会导致M1与程序的其他部分紧密耦合 . 这不是好设计 .

    但是,对于使用M1的模块在内部执行某种类型的控制可能是有意义的 . 假设我们有一个"module" M2实际上使用了许多软件包作为其实现的一部分 . M2中的"main"包(M2的客户端用来让M2执行其任务)使用M1创建一个新对象,然后将该对象传递给其他几个完成工作的包 . 似乎一个合理的设计目标是找到M2可以将该对象传递给某些包或子程序而不给予它们更新对象的能力,但是将其传递给具有该能力的其他包或子程序 .

    有一些解决方案可以防止大多数事故 . 例如:

    package M1 is
    
        type Secret is tagged private;
        procedure Harmless_Operation (X : in out Secret);
    
        type Secret_With_Updater is new Secret with null record;
        procedure Dangerous_Operation (X : in out Secret_With_Updater);
    
    end M1;
    

    现在,可以采用"Secret"对象但不应该具有更新能力的包将具有使用 Secret'Class 参数定义的过程 . M2将创建一个 Secret_With_Updater 对象;由于此对象类型位于 Secret'Class 中,因此可以将其作为参数传递给具有 Secret'Class 参数的过程 . 但是,这些程序无法在其参数上调用 Dangerous_Operation ;那不会编译 .

    具有 Secret'Class 参数的包仍然可以通过类型转换调用危险操作:

    procedure P (X : in out Secret'Class) is
    begin
        -- ...
        M1.Secret_With_Updater(X).Dangerous_Operation;
        -- ...
    end P;
    

    该语言可以使 Secret_With_Updater 对某些包可见,但对其他包不可见(不使用子包层次结构) . 但是偶然做这件事会更难 . 如果你真的希望更进一步,甚至阻止这一点(如果你认为会有一个程序员,他们对良好的设计原则的理解太差,以至于他们愿意编写这样的代码),那么你可以更进一步:

    package M1 is
    
        type Secret is tagged private;
        procedure Harmless_Operation (X : in out Secret);
        type Secret_Acc is access all Secret;
    
        type Secret_With_Updater is tagged private;
        function Get_Secret (X : Secret_With_Updater) return Secret_Acc;
            -- this will be "return X.S"
        procedure Dangerous_Operation (X : in out Secret_With_Updater);
    
    private
        -- ...
        type Secret_With_Updater is tagged record
            S : Secret_Acc;
        end record;
        -- ...
    end M1;
    

    然后,为了创建一个秘密,M2会调用一些东西来创建一个Secret_With_Updater,它返回一个可以访问Secret的记录 . 然后它将 X.Get_Secret 传递给那些不允许调用 Dangerous_Operation 的程序,但 X 本身传递给那些允许的程序 . (您可能也可以声明 S : aliased Secret ,声明 Get_Secret 以返回 access Secret ,并使用 return X.S'access 实现它 . 这可能会避免潜在的内存泄漏,但它也可能会遇到可访问性检查问题 . 我没有尝试过 . )

    无论如何,也许这些想法中的一些可以通过强制M1了解使用它的应用程序的结构来帮助实现您想要完成的任务而不引入不必要的耦合 . 这很难说,因为你对这个问题的描述,即使是图表,对于我来说仍然是一个过于抽象的层次,看你真正想要做什么 .

  • 2

    您的问题非常不清楚(并且所有C代码都无法帮助解释您的需求),但如果您的观点是您希望某个类型具有一些可公开访问的操作以及一些私有操作,那么很容易完成:

    package Example is
       type Instance is private;
    
       procedure Public_Operation (Item : in out Instance);
    private
       procedure Private_Operation (Item : in out Instance);
    
       type Instance is ... -- whatever you need it to be
    end Example;
    

    Example 的子女可以访问 Example.Private_Operation 程序 . 如果您希望操作纯粹是内部操作,则只在包体中声明它:

    package body Example is
       procedure Internal_Operation (Item : in out Instance);
    
       ...
    end Example;
    
  • 2

    好吧,我想知道在Ada中是否有可能出现这种情况 . 基本上我的愿望是能够说:代码A可能只能由代码B执行,而不能由任何其他人执行

    如果仅限于语言功能,没有 .

    以编程方式,如果必须向提供者提供允许执行其服务的批准“密钥”,则可以保护代码执行,并且仅向授权客户端提供这样的密钥 .

    设计这些键的性质,生成和安全性是留给读者的练习 .

相关问题