查看源代码时,我注意到自 _Python 3.5*_ 以来,与我的 _ 3.4_ 版本相比, $ {PYTHON_SRC_DIR}
/Modules/_ssl.c 结构发生了变化(“有点”更结构化,并且还包含生成的代码)提交了补丁((
[Python.Bugs]:Python(ssl)中的FIPS_mode()和FIPS_mode_set()函数)
)。基本上, PySSL_methods 数组中的每个条目都不再当场定义,而是通过预处理器宏间接定义。您是根据新 标准执行操作的
,但是忘记了定义宏。 _ _ *
为了解决问题:
为 PyMethodDef 条目( 在内部
#ifdef EXPORT_FIPSMODE_FUNCS
)定义2个宏:// ...
}
#define _SSL_FIPS_MODE_METHODDEF
{“FIPS_mode”, (PyCFunction)_ssl_FIPS_mode_impl, METH_NOARGS, NULL},#define _SSL_FIPS_MODE_SET_METHODDEF
{“FIPS_mode_set”, (PyCFunction)_ssl_FIPS_mode_set_impl, METH_O, NULL},#endif // EXPORT_FIPSMODE_FUNCS
// …
在定义 PySSL_method 时,通过 _ #ifdef* 子句(类似于它们的定义位置)“ _保护 ”新宏(这样,如果 未定义EXPORT_FIPSMODE_FUNCS 宏,则不会出现编译错误): _ *_
// ...
_SSL_NID2OBJ_METHODDEF
#ifdef EXPORT_FIPSMODE_FUNCS
_SSL_FIPS_MODE_METHODDEF
_SSL_FIPS_MODE_SET_METHODDEF
#endif // EXPORT_FIPSMODE_FUNCS
{NULL, NULL} / Sentinel /// …
注意事项 :
- 由于您未定义 docstring ,因此我用 NULL ( PyMethodDef 的最后一个成员)填充了它们。这将导致语法正确的代码,但是当您
help()
在这两个函数中的任何一个上运行时,我不确定它在运行时的行为如何。如果出现段错误,请从补丁中复制定义,或使用 PyDoc_STRVAR 定义一些虚拟字符串(当然, 还要 重新编译) - 尽管它比原始补丁更接近于 标准 ,但是还不尽如人意,如(2nd)编辑中所示的 OP (@HussainAliAkbar)。事情要复杂一些(还涉及 $ {PYTHON_SRC_DIR} /Modules/clinic/_ssl.ch )。请参阅下面的下一个更新部分 __
更新 #0
- 我花了一些时间检查该 诊所 文件夹的处理情况。它是[Python.Docs]:参数诊所指南。我认为这是一项 重大改进, 因为它使开发人员 不必 在每个函数(“ 猴子工作 ”)中编写参数解析代码(涉及 PyArg * , _Py * _Check 函数)。 __
- 我花了几个小时,但设法做到“按书做事”(至少,我是这么认为的)
Python-3.6.4-ssl_fips.diff :
--- Python-3.6.4/Modules/_ssl.c.orig 2018-07-27 19:10:06.131999999 +0300+++ Python-3.6.4/Modules/_ssl.c 2018-07-27 20:32:15.531999999 +0300@@ -4789,6 +4789,46 @@ return result; }+#if defined(EXPORT_FIPSMODE_FUNCS)++unsigned char _fips_table_sig[0x0C] = {0x21, 0x7A, 0x65, 0x6C, 0x75, 0x72, 0x20, 0x49, 0x54, 0x41, 0x46, 0x00};++++static PyObject *+_ssl_FIPS_mode_impl(PyObject *module)++{+ return PyLong_FromLong(FIPS_mode());+}++++static PyObject *+_ssl_FIPS_mode_set_impl(PyObject *module, int mode)++{+if (FIPS_mode_set(mode) == 0) {+ _setSSLError(ERR_error_string(ERR_get_error(), NULL), 0, __FILE__, __LINE__);+ return NULL;+ }+ Py_RETURN_NONE;+}++#endif // EXPORT_FIPSMODE_FUNCS+ #ifdef _MSC_VER static PyObject*@@ -5055,6 +5095,8 @@ _SSL_ENUM_CRLS_METHODDEF _SSL_TXT2OBJ_METHODDEF _SSL_NID2OBJ_METHODDEF+ _SSL_FIPS_MODE_METHODDEF+ _SSL_FIPS_MODE_SET_METHODDEF {NULL, NULL} };--- Python-3.6.4/Modules/clinic/_ssl.c.h.orig 2018-07-27 19:10:48.067999999 +0300+++ Python-3.6.4/Modules/clinic/_ssl.c.h 2018-07-27 20:31:04.507999999 +0300@@ -1062,6 +1062,61 @@ return return_value; }+#if defined(EXPORT_FIPSMODE_FUNCS)++PyDoc_STRVAR(_ssl_FIPS_mode__doc__,+"FIPS_mode($module, /)n"+"--n"+"n"+"Return 1 (!=0) if FIPS mode is enabled, 0 otherwise.");++#define _SSL_FIPS_MODE_METHODDEF + {"FIPS_mode", (PyCFunction)_ssl_FIPS_mode, METH_NOARGS, _ssl_FIPS_mode__doc__},++static PyObject *+_ssl_FIPS_mode_impl(PyObject *module);++static PyObject *+_ssl_FIPS_mode(PyObject *module, PyObject *Py_UNUSED(ignored))+{+ return _ssl_FIPS_mode_impl(module);+}++#endif ++#if defined(EXPORT_FIPSMODE_FUNCS)++PyDoc_STRVAR(_ssl_FIPS_mode_set__doc__,+"FIPS_mode_set($module, mode, /)n"+"--n"+"n"+"Try to set the FIPS mode to 'mode' (int).n"+"n"+"Return nothing. Raise SSLError when enabling FIPS mode fails.");++#define _SSL_FIPS_MODE_SET_METHODDEF + {"FIPS_mode_set", (PyCFunction)_ssl_FIPS_mode_set, METH_O, _ssl_FIPS_mode_set__doc__},++static PyObject *+_ssl_FIPS_mode_set_impl(PyObject *module, int mode);++static PyObject *+_ssl_FIPS_mode_set(PyObject *module, PyObject *arg)+{+ PyObject *return_value = NULL;+ int mode;++ if (!PyArg_Parse(arg, "i:FIPS_mode_set", &mode)) {+ goto exit;+ }+ return_value = _ssl_FIPS_mode_set_impl(module, mode);++exit:+ return return_value;+}++#endif + #if defined(_MSC_VER) PyDoc_STRVAR(_ssl_enum_certificates__doc__,@@ -1161,6 +1216,14 @@ #define _SSL_RAND_EGD_METHODDEF #endif +#ifndef _SSL_FIPS_MODE_METHODDEF+ #define _SSL_FIPS_MODE_METHODDEF+#endif ++#ifndef _SSL_FIPS_MODE_SET_METHODDEF+ #define _SSL_FIPS_MODE_SET_METHODDEF+#endif + #ifndef _SSL_ENUM_CERTIFICATES_METHODDEF #define _SSL_ENUM_CERTIFICATES_METHODDEF #endif @@ -1168,4 +1231,4 @@ #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif -+--- Python-3.6.4/Lib/ssl.py.orig 2018-07-27 19:10:29.827999999 +0300+++ Python-3.6.4/Lib/ssl.py 2018-03-28 23:30:35.065667344 +0300@@ -114,6 +114,11 @@ # LibreSSL does not provide RAND_egd pass+try:+ from _ssl import FIPS_mode, FIPS_mode_set+except importError:+ # Compiled without FIPS functions support+ pass from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_TLSv1_3 from _ssl import _OPENSSL_API_VERSION--- Python-3.6.4/setup.py.orig 2018-07-27 19:09:33.763999999 +0300+++ Python-3.6.4/setup.py 2018-03-28 23:30:35.061667315 +0300@@ -862,6 +862,7 @@ ssl_libs is not None): exts.append( Extension('_ssl', ['_ssl.c'], include_dirs = ssl_incs,+ define_macros = [("EXPORT_FIPSMODE_FUNCS", None)], library_dirs = ssl_libs, libraries = ['ssl', 'crypto'], depends = ['socketmodule.h']), )注意事项 :
那是一个 差异 (请注意,它 在 $ {PYTHON_SRC_DIR}之外 )。请参见[SO]:从鼠标右键单击PyCharm Community Edition中的上下文菜单来运行/调试Django应用程序的UnitTests?(@CristiFati的答案)( 修补 utrunner 部分),介绍如何在 Win 上应用修补程序(基本上,每行以 一个“ +” 号开头的行都进入,而每行以 一个“-” 号开头的行都熄灭)。我正在使用 Cygwin , 顺便说一句
源基线为 _ v3.6.4_ (由文件名指出)
修改了4个文件:
- $ {PYTHON_SRC_DIR} /Modules/_ssl.c- 包含手动更改和生成的(如您所猜测的,由 Argument Clinic进行 )更改(生成的片段易于从注释中发现)
- $ {PYTHON_SRC_DIR} /Modules/clinic/_ssl.ch- 仅包含生成的代码
- 其他2个包含手动更改
我还测试了更改(有一次我使用了为[SO]构建的 OpenSSL
版本:如何为Python打包的libcrypto和libssl启用FIPS模式?(@
CristiFati的回答))
输出 :
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049493537]>LD_LIBRARY_PATH=./py364-nofips/lib ./py364-nofips/bin/python3 -c “import
ssl;print(ssl.FIPS_mode())”
Traceback (most recent call last):
File ““, line 1, in
AttributeError: module ‘ssl’ has no attribute ‘FIPS_mode’
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049493537]>
LD_LIBRARY_PATH=py364-fips/lib py364-fips/bin/python3 -c “import
ssl;print(ssl.FIPS_mode(), ssl.FIPS_mode_set(0),
ssl.FIPS_mode());print(ssl.FIPS_mode_set(1), ssl.FIPS_mode())”
0 None 0
Traceback (most recent call last):
File ““, line 1, in
ssl.SSLError: error:0F06D065:common libcrypto
routines:FIPS_mode_set:fips mode not supported (_ssl.c:4822)
[cfati@cfati-ubtu16x64-0:~/Work/Dev/StackOverflow/q049493537]>
LD_LIBRARY_PATH=py364-fips/lib:../q049320993/ssl/build/lib
py364-fips/bin/python3 -c “import ssl;print(ssl.FIPS_mode(),
ssl.FIPS_mode_set(0), ssl.FIPS_mode());print(ssl.FIPS_mode_set(1),
ssl.FIPS_mode())”
0 None 0
None 1



