gpt4 book ai didi

c - 在 C 中为 PAM 模块(.so 文件)嵌入 Python 脚本时出现 ImportError 和 PyExc_SystemError

转载 作者:太空狗 更新时间:2023-10-29 16:11:49 25 4
gpt4 key购买 nike

我正在尝试用 C 编写一个演示 PAM 模块,它使用在 C 概念中嵌入 Python 来运行用 python (2.7) 编写的脚本,在 pam_sm_authenticate() 函数中,该函数是用 C 文件 (pam_auth.c) 编写的).

这是python脚本:test.py

import math
import numpy
def test_func():
a = "test"
return a

test.py 的路径是/usr/lib/Python2.7/这样我就可以很容易地导入它。

这是 C 文件:

#define PAM_SM_AUTH
#define PAM_SM_ACCOUNT
#define PAM_SM_SESSION

#include <security/pam_modules.h>
#include <security/_pam_macros.h>
#include <security/pam_appl.h>
#include<python2.7/Python.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define NOBODY "nobody"


/*PAM Stuffs*/

PAM_EXTERN int pam_sm_authenticate(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
const char *user;
int retval;
user = NULL;
retval = pam_get_user(pamh, &user, NULL);
if(retval != PAM_SUCCESS)
{
fprintf(stderr, "%s", pam_strerror(pamh, retval));
// return (retval);
}
fprintf(stdout, "retval= %d user=%s\n", retval,user);
if (user == NULL || *user =='\0')
pam_set_item(pamh, PAM_USER, (const char*)NOBODY);

/* Python Wrapper */

// Set PYTHONPATH TO working directory
//int res = setenv("PYTHONPATH",".",1);
//fprintf(stdout, "%d", res);

PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pResult;

// Initialize the Python Interpreter
Py_Initialize();

// Build the name object
pName = PyString_FromString((char*)"test");

// Load the module object
pModule = PyImport_Import(pName);

// pDict is a borrowed reference

PyErr_Print();
pDict = PyModule_GetDict(pModule);

// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, (char*)"test_func");

if (PyCallable_Check(pFunc))
{
pValue=NULL;
PyErr_Print();
pResult=PyObject_CallObject(pFunc,pValue);
PyErr_Print();
}else
{
PyErr_Print();
}
printf("Result is %s\n",PyString_AsString(pResult));

// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);/* */

// Finish the Python Interpreter
Py_Finalize();

return PAM_SUCCESS;
}

PAM_EXTERN int pam_sm_setcred(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}

PAM_EXTERN int pam_sm_acct_mgmt(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}

PAM_EXTERN int pam_sm_open_session(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}

PAM_EXTERN int pam_sm_close_session(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}

PAM_EXTERN int pam_sm_chauthtok(
pam_handle_t* pamh, int flags, int argc, const char** argv)
{
return PAM_SUCCESS;
}

C 文件只是 pam_permit.c 的修改版。 C文件使用gcc(gcc -shared -o pam_auth.so -fPIC pam_auth.c -I/usr/include/python2.7 -lpython2.7)编译得到.so文件(pam_auth.so)并放入在文件夹/lib/security/中

我在/etc/pam.d 中更改了“sudo”文件的 PAM 配置,如下所示:

#%PAM-1.0

auth required pam_env.so readenv=1 user_readenv=0
auth required pam_env.so readenv=1 envfile=/etc/default/locale user_readenv=0
#@include common-auth #this line is commented to make it use my pam module
auth required pam_auth.so
@include common-account
@include common-session-noninteractive

每次我使用命令“sudo”时,“auth required pam_auth.so”行强制系统使用我的模块进行身份验证。 (for ex- sudo nautilus)

现在的问题是:C 文件“pModule = PyImport_Import(pName);”中的这一行给出了导入错误,由 PyErr_Print() 打印如下:

stitches@Andromida:~$ sudo nautilus
retval= 0 user=stitches
Traceback (most recent call last):
File "/usr/lib/python2.7/subho_auth.py", line 8, in <module>
import numpy
File "/usr/lib/python2.7/dist-packages/numpy/__init__.py", line 153, in <module>
from . import add_newdocs
File "/usr/lib/python2.7/dist-packages/numpy/add_newdocs.py", line 13, in <module>
from numpy.lib import add_newdoc
File "/usr/lib/python2.7/dist-packages/numpy/lib/__init__.py", line 8, in <module>
from .type_check import *
File "/usr/lib/python2.7/dist-packages/numpy/lib/type_check.py", line 11, in <module>
import numpy.core.numeric as _nx
File "/usr/lib/python2.7/dist-packages/numpy/core/__init__.py", line 6, in <module>
from . import multiarray
ImportError: /usr/lib/python2.7/dist-packages/numpy/core/multiarray.so: undefined symbol: PyExc_SystemError
Segmentation fault (core dumped)

据我所知,它无法导入 test.py 文件中指定的 numpy 库。如何解决ImportError & PyExc_SystemError 问题?

如果我按如下方式运行,python 脚本就可以正常工作:

#include <Python.h>
#include <stdlib.h>
#include <string.h>
int main()
{
// Set PYTHONPATH TO working directory
//int res = setenv("PYTHONPATH",".",1);
//fprintf(stdout, "%d", res);

PyObject *pName, *pModule, *pDict, *pFunc, *pValue, *pResult;

// Initialize the Python Interpreter
Py_Initialize();

// Build the name object
pName = PyString_FromString((char*)"test");

// Load the module object
pModule = PyImport_Import(pName);

// pDict is a borrowed reference

PyErr_Print();
pDict = PyModule_GetDict(pModule);

// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, (char*)"test_func");

if (PyCallable_Check(pFunc))
{
pValue=NULL;
PyErr_Print();
pResult=PyObject_CallObject(pFunc,pValue);
PyErr_Print();
}else
{
PyErr_Print();
}
printf("Result is %s\n",PyString_AsString(pResult));

// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);/* */

// Finish the Python Interpreter
Py_Finalize();

return 0;
}

如果它在一般的 python 嵌入示例下工作,为什么它在基于 PAM 的嵌入示例(使用 .so 文件的地方)中不起作用?

PS:出于特殊原因,我正在导入 numpy。不要问为什么我没有在任何地方使用 python 脚本,因为这只是我想要实现的演示脚本。此外,导入数学不会给出任何导入错误。我也收到 SciPY 的导入错误。

PPS:Numpy 和 Scipy 包在 python 脚本中运行完美,安装在/usr/lib/python2.7/dist-packages/下。我正在使用 ubuntu 14.04。

请帮忙!!!!

最佳答案

我不知道你问题的答案,但我想知道为什么它没有早点失败。主机应用程序不知道您的 PAM 模块将需要使用 libpython2.7.so.1,因此必须以某种方式动态加载,否则 Py_Initialize() 调用将失败并出现相同的错误。

既然你说它不会在那里失败,它就必须被加载。但是,根据您收到的错误,我们可以推断出它包含的符号(例如 PyExc_SystemError)对于随后加载的动态库是不可见的。这是使用 dlopen() 加载库时的默认设置(参见 man 3 dlopen 中的 RTLD_LOCAL)。要覆盖它,您必须将 RTLD_GLOBAL 传递给 dlopen()。也许这是你的问题。

关于您的代码的其他评论:

  • 为每个 pm_sm_...() 调用调用 Py_Initialise() 将是昂贵的并且可能对 python 模块来说是令人惊讶的。这意味着 python 模块在一次调用中积累的所有数据(比如语音或用户名)将在下一次调用时被丢弃。您最好加载 libpython2.7.so.1 并初始化 PAM 一次,然后在完成后使用 pam_set_data() 的清理函数卸载它。

  • 在一个相关问题中,您的 PAM 模块无法在 Python 程序中使用,因为您总是调用 Py_Initialise()(并且我假设匹配调用 Py_Finalize()).

  • 如果您的程序没有掉落到它掉落的地方,它就会在 printf("Result is %s\n",PyString_AsString(pResult)) 行上掉落,因为pResult 未初始化。

  • 我想您知道,此处所有可让您在 Python 中编写 PAM 模块的样板文件均由 pam-python 提供。 - 不需要 C。由于您显然是在用 Python 编写 PAM 模块,因此您已经接触到它产生的开销,但错过了它提供的功能,例如记录未捕获的 Python 异常。最重要的是,使用它意味着您可以完全避免使用 C。您的 PAM 模块将被加载到保护机器安全的程序中 - 像 login、sudo 和 xdm/gdm3 这样的程序。避免 C 也意味着避免 C 程序可能存在的大量安全漏洞,而这在 Python 中是不可能的——缓冲区溢出、未初始化的指针和访问释放的内存。由于您在此处发布的 C 代码中存在其中一个错误,因此避免它听起来是个好主意。

关于c - 在 C 中为 PAM 模块(.so 文件)嵌入 Python 脚本时出现 ImportError 和 PyExc_SystemError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29880931/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com