RSA 身份验证代理 API 文档中的函数签名是否正确?

2024-03-09

我有一些使用 RSA 身份验证代理记录的 API 的软件。该产品作为服务在域中的客户端计算机上运行,​​并通过与集中安装的“RSA 身份验证管理器”通信来对本地用户进行身份验证。

身份验证代理的 API 公开记录在此处:适用于 C 开发人员指南的身份验证代理 API 8.1.1 https://community.rsa.com/docs/DOC-36840。但是,文档似乎不正确,并且我无权访问 RSA 头文件 - 它们不是公开的;仅 PDF 文档可供下载,无需向 RSA 支付费用。如果这里有人可以访问最新头文件,你能帮我确认一下文档是否已经过时了吗?

API 文档中给出的函数签名似乎不正确 - 事实上,我绝对确信它们在 x64 机器上是错误的。例如,最新的 PDF 文档显示以下内容:

int WINAPI AceSetUserData(SDI_HANDLE hdl, unsigned int userData)
int WINAPI AceGetUserData(SDI_HANDLE hdl, unsigned int *pUserData)

该文档多次指出“userData”值是一个 32 位数量,例如在文档中AceInit, AceSetUserData, and AceGetUserData。文档的相关摘录AceGetUserData:

该函数是同步的,调用者必须提供一个指向 32 位存储区域(即无符号整数)的指针作为第二个参数,以便将用户数据值复制到其中。

这显然是错误的 - 从一些实验来看,如果您传入一个指向填充有 0xff 的缓冲区中心的指针,AceGetUserData is 确实写出 64 位值,而不是 32 位数量。

我的版本aceclnt.dll是 8.1.3.563;相应的文档标记为“Authentication Agent API 8.1 SP1”,这对应于 Authentication Agent 本身的版本 7.3.1。

测试代码

给出了完整的测试代码,即使它与问题根本无关...如果其他人运行测试代码对我来说没有用(我知道它的作用!),我需要的是有权访问 RSA 标头的人可以确认函数签名的文件。

#include <assert.h>
#include <stdlib.h>
#include <stdint.h>

#ifdef WIN32
#include <Windows.h>
#include <tchar.h>
#define SDAPI WINAPI
#else
#define SDAPI
#endif
typedef int SDI_HANDLE;
typedef uint32_t SD_BOOL;
typedef void (SDAPI* AceCallback)(SDI_HANDLE);
#define ACE_SUCCESS                    1
#define ACE_PROCESSING                 150

typedef SD_BOOL (SDAPI* AceInitializeEx_proto)(const char*, char*, uint32_t);
typedef int (SDAPI* AceInit_proto)(SDI_HANDLE*, void*, AceCallback);
typedef int (SDAPI* AceClose_proto)(SDI_HANDLE, AceCallback);

typedef int (SDAPI* AceGetUserData_proto)(SDI_HANDLE, void*);
typedef int (SDAPI* AceSetUserData_proto)(SDI_HANDLE, void*);

struct Api {
  AceInitializeEx_proto AceInitializeEx;
  AceInit_proto AceInit;
  AceClose_proto AceClose;
  AceGetUserData_proto AceGetUserData;
  AceSetUserData_proto AceSetUserData;
} api;

static void api_init(struct Api* api) {
  // All error-checking stripped...
  HMODULE dll = LoadLibrary(_T("aceclnt.dll")); // leak this for the demo
  api->AceInitializeEx = (AceInitializeEx_proto)GetProcAddress(dll, "AceInitializeEx");
  api->AceInit = (AceInit_proto)GetProcAddress(dll, "AceInit");
  api->AceClose = (AceClose_proto)GetProcAddress(dll, "AceClose");
  api->AceGetUserData = (AceGetUserData_proto)GetProcAddress(dll, "AceGetUserData");
  api->AceSetUserData = (AceSetUserData_proto)GetProcAddress(dll, "AceSetUserData");

  int success = api->AceInitializeEx("C:\\my\\conf\\directory", 0, 0);
  assert(success);
}

static void demoFunction(SDI_HANDLE handle) {
  union {
    unsigned char testBuffer[sizeof(void *) * 3];
    void *forceAlignment;
  } u;

  memset(u.testBuffer, 0xA5, sizeof u.testBuffer);

  int err = api.AceGetUserData(handle, (void*)(u.testBuffer + sizeof(void*)));
  assert(err == ACE_SUCCESS);

  fputs("DEBUG: testBuffer =", stderr);
  for (size_t i = 0; i < sizeof(u.testBuffer); i++) {
    if (i % 4 == 0)
      putc(' ', stderr);
    fprintf(stderr, "%02x", u.testBuffer[i]);
  }
  fputc('\n', stderr);
  // Prints:
  // DEBUG: testBuffer = a5a5a5a5 a5a5a5a5 00000000 00000000 a5a5a5a5 a5a5a5a5
  // According to the docs, this should only write out a 32-bit value
}

static void SDAPI demoCallback(SDI_HANDLE h) {
  fprintf(stderr, "Callback invoked, handle = %p\n", (void*)h);
}

int main(int argc, const char** argv)
{
  api_init(&api);
  SDI_HANDLE h;

  int err = api.AceInit(&h, /* contentious argument */ 0, &demoCallback);
  assert(err == ACE_PROCESSING);

  demoFunction(h);

  api.AceClose(h, 0);

  return 0;
}

当您从文档中复制函数/类型定义时,您基本上没有也永远不会拥有您正在使用的 .dll 版本的正确定义,并且可能总是以崩溃或更糟的情况而告终,未定义行为。

你可以做的是调试相应的.dll:

你运行 Visual Studio 吗?我记得 VS 可以在调试模式下输入函数调用并显示程序集,但现在不确定情况如何。但任何反汇编程序都应该可以做到这一点。作为x64 ABI https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx登记rcx得到第一个参数,rdx第二。如果函数内部使用 32 位寄存器名称或清除高 32 位,则可以假定为 32 位整数。如果它使用它来加载地址(例如lea指令)你可以假设一个指针。但正如你所看到的,这可能不是你想要走的路......

那么你还剩下什么呢?

您链接的文档说明了 32 位和 64 位库 - 取决于您使用的平台。我猜您使用的是 64 位库,并且 RSA 没有更新该库的文档,但在某些时候开发人员需要将该库升级到 64 位。

因此,请这样想:如果您是 API 开发人员,什么可以迁移到 64 位,什么不可以。例如。需要跨 32/64 实现工作的所有内容(通过网络发送或在磁盘上存储和共享的内容)都无法触及。但实例本地的所有内容都可以迁移。作为userData似乎是一个运行时的事情,支持平台提供的任何内容都是有意义的:unsigned long在 64 位和unsigned int在 32 位上。

你已经明白了userData必须是 64 位。但这并不是因为该函数写出了 64 位整数,而是因为该函数首先看到的是 64 位值。由于整数是按值传递的(我猜一般来说,但绝对是在WINAPI https://msdn.microsoft.com/en-us/library/zxk0tw93.aspx),如果它是 32 位数据类型,则该函数绝对不可能看到完整的 64 位值。因此,API 开发人员很可能将数据类型更改为unsigned long(无论如何都是 64 位类型)。

PS:如果您最终将指针放入 userData 中,请将指针强制转换为uintptr_t并存储/读取该类型。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RSA 身份验证代理 API 文档中的函数签名是否正确? 的相关文章

  • C++ 维护子类对象的混合集合

    如果我在这里错过了一个相当基本的概念 我很抱歉 但我正在尝试弄清楚如何维护多个类类型的集合 所有类类型都派生自同一个父类 并且在检索它们时仍然可以访问它们的特定于子类的方法从集合中 作为上下文 我有一个基类 BaseClass 和许多类 例
  • GetType() 在 Type 实例上返回什么?

    我在一些调试过程中遇到了这段代码 private bool HasBaseType Type type out Type baseType Type originalType type GetType baseType GetBaseTyp
  • ComboBox DataBinding 导致 ArgumentException

    我的几个类对象 class Person public string Name get set public string Sex get set public int Age get set public override string
  • IdentityServer 4 对它的工作原理感到困惑

    我阅读和观看了很多有关 Identity Server 4 的内容 但我仍然对它有点困惑 因为似乎有很多移动部件 我现在明白这是一个单独的项目 它处理用户身份验证 我仍然不明白的是用户如何注册它 谁存储用户名 密码 我打算进行此设置 Rea
  • JNI 将 Char* 2D 数组传递给 JAVA 代码

    我想从 C 代码通过 JNI 层传递以下指针数组 char result MAXTEST MAXRESPONSE 12 12 8 3 29 70 5 2 42 42 在java代码中我写了以下声明 public static native
  • 如何填充 ToolStripComboBox?

    我发现它很难将数据绑定到ToolStripComboBox 好像没有这个ValueMember and DisplayMember特性 怎么绑定呢 访问toolstripcombobox中包装的组合框并访问其ValueMember Disp
  • 查看 NuGet 包依赖关系层次结构

    有没有一种方法 文本或图形 来查看 NuGet 包之间的依赖关系层次结构 如果您使用的是新的 csproj 您可以在此处获取所有依赖项 在项目构建后 项目目录 obj project assets json
  • 对 std::vector 进行排序但忽略某个数字

    我有一个std vector
  • Python 属性和 Swig

    我正在尝试使用 swig 为一些 C 代码创建 python 绑定 我似乎遇到了一个问题 试图从我拥有的一些访问器函数创建 python 属性 方法如下 class Player public void entity Entity enti
  • File.AppendText 尝试写入错误的位置

    我有一个 C 控制台应用程序 它作为 Windows 任务计划程序中的计划任务运行 此控制台应用程序写入日志文件 该日志文件在调试模式下运行时会创建并写入应用程序文件夹本身内的文件 但是 当它在任务计划程序中运行时 它会抛出一个错误 指出访
  • 在Linux中,找不到框架“.NETFramework,Version=v4.5”的参考程序集

    我已经设置了 Visual studio 来在我的 Ubuntu 机器上编译 C 代码 我将工作区 我的代码加载到 VS 我可以看到以下错误 The reference assemblies for framework NETFramewo
  • 将 Long 转换为 DateTime 从 C# 日期到 Java 日期

    我一直尝试用Java读取二进制文件 而二进制文件是用C 编写的 其中一些数据包含日期时间数据 当 DateTime 数据写入文件 以二进制形式 时 它使用DateTime ToBinary on C 为了读取 DateTime 数据 它将首
  • 为什么可以通过ref参数修改readonly字段?

    考虑 class Foo private readonly string value public Foo Bar ref value private void Bar ref string value value hello world
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 识别 Visual Studio 中的重载运算符 (c++)

    有没有办法使用 Visual Studio 快速直观地识别 C 中的重载运算符 在我看来 C 中的一大问题是不知道您正在使用的运算符是否已重载 Visual Studio 或某些第三方工具中是否有某些功能可以自动突出显示重载运算符或对重载运
  • 打破 ReadFile() 阻塞 - 命名管道 (Windows API)

    为了简化 这是一种命名管道服务器正在等待命名管道客户端写入管道的情况 使用 WriteFile 阻塞的 Windows API 是 ReadFile 服务器已创建启用阻塞的同步管道 无重叠 I O 客户端已连接 现在服务器正在等待一些数据
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • WPF DataGridTemplateColumn 组合框更新所有行

    我有这个 XAML 它从 ItemSource 是枚举的组合框中选择一个值 我使用的教程是 http www c sharpcorner com uploadfile dpatra combobox in datagrid in wpf h

随机推荐