openssl_uplink no openssl_applink

调用PEM_read_RSAPrivateKey时程序直接退出,跟踪发现,执行到了一个unimplemented(),此函数调用OPENSSL_showfatal后就exit了
fatal内容如下:
openssl_uplink no openssl_applink

原因:
openssl 在一些文件I/O时不用标准的C库函数,而是自己用了22个函数代替,例如 在打开文件时不直接使用 fopen, 而是使用 UP_fopen
但是在libeay32.dll中并没有实现这些函数。它要求调用者来实现,反过来供自己使用。调用者怎么实现呢?这个openssl倒是已经准备好了,调用者需要将applink.c添加到自己的工程项目中,重新编译即可。

在applink.c里面,我们看到,UP_fopen还是#include使用标准的C库函数。
为什么不直接fopen,而要绕这么大一个圈子呢?
我们姑且假设openssl有充分的理由这么做,那么第2个问题是:
为什么不直接在libeay32.dll中实现这22个函数,而要调用者实现?

第1个问题,搜索了一下,发现了一个答案:

https://github.com/openssl/openssl/pull/1356

Mixing threading models is only one particular case. I mean issue is wider than that. Intention was to facilitate mixing different compilers and/or versions, or even compiler flags. I mean say you want to compiler your application with debugging flags. Without applink you’d have to recompile even OpenSSL dlls with same flags… Or consider I’ve got dll from somebody else, without applink you’d have to figure out which compiler version was used and use same. With applink you can use any compiler, not even from same vendor. Once again, if you use interfaces that actually rely on applink. As correctly pointed out those accepting FILE * and Unix-like fd from application. And once again, recommendation is avoid those in new application code.

感到理由不那么充分

继续往下读

threading models.
During compilation, the MSVCRT assumes the layout of FILE objects. In multi-threaded builds, FILE objects include an extra CRITICAL_SECTION field to provide locking. The MSVCRT maintains a list of these objects in an array _iob. If one part of an application is built with a different threading model it can lead to memory corruption of the _iob array, lost data and application crash.

Applink solves this by moving all file i/o out of OpenSSL and into your application. But this introduces a problem for those developers working in scripting languages, where the application is the interpreter (ex: python). It may not be practical to request users to rebuild the interpreter.

In the case where you are developing c extensions for your scripting language you can instead arrange to include in your extension and from there invoke OPENSSL_SetApplink. This requires that your extension be compiled using the same threading model as the application and as OpenSSL.

这个理由足够了。

第1个问题弄明白了后,发现第2个问题不需要问了。因为假如在libeay32.dll中实现,那么效果将是这样的:
fopen = UP_fopen
UP_fopen(FILE *fp, int mode){
fopen(fp, mode)
}
哈哈,这没有解决任何问题

关键: openssl不知道你的程序使用什么模式编译的,只有你自己知道,因此你要自己来避免模式不匹配造成的内存泄露

Leave a Reply

Your email address will not be published. Required fields are marked *