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

2023-12-14

我正在尝试用 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 的修改。使用 gcc ( gcc -shared -o pam_auth.so -fPIC pam_auth.c -I/usr/include/python2.7 -lpython2.7 ) 编译 C 文件以获得 .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”行都会强制系统使用我的模块进行身份验证。 (对于前 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。

请帮忙!!!!


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

既然你说它不会失败,那么它必须被加载。但是,从您收到的错误中,我们可以推断出它包含的符号(例如PyExc_系统错误)对于随后加载的动态库不可见。这是使用加载库时的默认设置dlopen() (see RTLD_LOCAL in 男人 3 dlopen)。要覆盖它,您必须通过RTLD_GLOBAL to dlopen()。也许这就是你的问题。

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

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

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

  • 如果你的程序没有在原来的地方跌倒,它就会在线路上跌倒printf("结果是 %s\n",PyString_AsString(pResult))因为pResult没有初始化。

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

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

在 PAM 模块(.so 文件)的 C 中嵌入 Python 脚本时出现 ImportError 和 PyExc_SystemError 的相关文章

  • 我如何才能等待多个事情

    我正在使用 C 11 和 stl 线程编写一个线程安全队列 WaitAndPop 方法当前如下所示 我希望能够将一些内容传递给 WaitAndPop 来指示调用线程是否已被要求停止 如果 WaitAndPop 等待并返回队列的元素 则应返回
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 如何在Python中对类别进行加权随机抽样

    给定一个元组列表 其中每个元组都包含一个概率和一个项目 我想根据其概率对项目进行采样 例如 给出列表 3 a 4 b 3 c 我想在 40 的时间内对 b 进行采样 在 python 中执行此操作的规范方法是什么 我查看了 random 模
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 创建链表而不将节点声明为指针

    我已经在谷歌和一些教科书上搜索了很长一段时间 我似乎无法理解为什么在构建链表时 节点需要是指针 例如 如果我有一个节点定义为 typedef struct Node int value struct Node next Node 为什么为了
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags

随机推荐

  • IE中的z索引问题

    我有一张地图 上面有一些点 用户将鼠标悬停在上面即可显示更多信息 我遇到的问题很难解释 因为只有当用户在 IE 中查看页面并且该页面托管在我的服务器上时 它才似乎是一个问题 下面的 jsfiddle 页面上的完全相同的代码可以正常工作 ht
  • 获取对象属性之间的最小/最大值的快速方法

    我在 javascript 中有一个像这样的对象 a 4 b 0 5 c 0 35 d 5 有没有一种快速方法可以获取属性中的最小值和最大值 而不必循环遍历所有属性 因为我拥有的对象很大 我需要每两秒获取一次最小值 最大值 对象的值不断变化
  • Android:获取手机硬件信息

    我正在开发告诉用户有关设备的应用程序 我问了很多关于SO的问题但没有找到答案 我想找到 型号 安卓版本 基带版本 内核版本 内部版本号 内存 我的手机 我非常感谢任何有关此问题的帮助 我在我的代码中使用了这个 所以我把所有的 Log i T
  • ER 图中的关系属性

    实体关系图中的关系是否可以有自己的关键属性 如果没有 那么我们是否必须用这个密钥创建一个单独的实体 唯一拥有自己的密钥的关系是多对多关系 这种关系的关键自然是其每个父母的外键的组合 如果关系还有其他属性 那么它根本就不是关系 它本身就是一个
  • Tortoise SVN - 将主干合并到分支 - 树冲突

    我们使用的是 SVN 1 8 我也在使用 Tortoise SVN 1 8 主要代码位于 project trunk 我将要做一个大的改变 所以我创建了一个分支 project branches x那是的副本 project trunk 作
  • JTextArea的append()方法似乎不起作用

    我们被分配创建一个简单的编译器作为家庭作业 它将接受一组指令 包含变量 条件 跳转等 并对其进行评估 这已经完成了 但我想我应该让我的程序更加 闪亮 并添加从文本文件加载指令的能力 只是为了用户舒适 然而 似乎JTextArea s app
  • 具有“独特部分正则表达式”的高级“uniq”

    uniq是一个工具 可以一次过滤文件中的行 以便仅显示唯一的行 uniq有一些支持来指定两条线何时 等效 但选项有限 我正在寻找一个工具 扩展uniq允许人们输入正则表达式 如果两条线捕获的组相同 则两条线被视为 等效 对于每个等价类 仅返
  • Java:引用意味着多少内存?

    正如问题所说 Java 编程语言中对对象的引用使用了多少内存 请 如果您有可靠的来源就更好了 多谢 它不是由语言或 JVM 规范指定的 然而 人们普遍认为 任何合理的实现在 32 位机器上都是 4 字节 在 64 位机器上是 4 到 8 字
  • 执行带有超时的 shell 函数

    为什么这会起作用 timeout 10s echo foo bar foo bar 但这不会 function echoFooBar echo foo bar echoFooBar foo bar timeout 10s echoFooBa
  • 从 self.navigationItem (在 UINavigationController 内部)打开时,UIPopoverController 不会被关闭

    我在关闭从 UINavigationController 的 navigationItem 启动的弹出窗口时遇到问题 看来由 UINavigationController 插入的导航项不会触发 UIPopoverController 的解除
  • 让 var_dump 看起来很漂亮[重复]

    这个问题在这里已经有答案了 我有一个简单的 GET 查询变量集 用于在从数据库中提取查询时显示测试数据 div style padding 24px background fff text align center table tr sty
  • 为什么在Python中设置pop返回第一个元素而list pop返回最后一个元素

    这有点令人困惑 它实际上来自堆栈吗pop push术语 L pop index gt item 删除并返回索引处的项目 默认为最后一个 如果列表为空或索引超出范围 则引发 IndexError gt gt gt 1 2 pop 2 删除并返
  • 递归:带有 `scipy.lfilter` 的 IIR 滤波器

    给定一些数据x from pandas datareader data import DataReader as dr x np squeeze dr DTWEXB fred dropna values 我想计算另一个向量y如下 Where
  • 使用 Python sendmail 设置 MIME 消息的返回路径

    您好 我想为我使用 Python 发送的 MIME 消息设置 Return Path 标头 基本上 我尝试过这样的事情 message MIMEMultipart message add header Return Path email p
  • 过滤掉标签属性或 CSS 中具有“display:none”的 HTML 元素

    假设您有一些用 Selenium 抓取并用 BeautifulSoup 解析的 html 源代码 from selenium import webdriver from bs4 import BeautifulSoup driver web
  • 实体框架 ID 自动递增

    增量有问题 我创建了一个新对象并尝试将其设置到我的数据库中我收到了数据违规错误 表中的索引未增加 Id 0 Id 设置为 SQL 表中的主键StoredGeneratedPatternEDM 中字段 Id 的属性设置为 Identity 因
  • javascript 中函数声明后的空括号 () 有何作用? [复制]

    这个问题在这里已经有答案了 我正在尝试阅读原型源 我已经到了这一部分 不幸的是 这个片段是在开头 这是什么意思 Browser function var ua navigator userAgent var isOpera Object p
  • 将联系人保存到 SIM 卡

    我想保存contact to sim卡 但我无法做到这一点 我用这个代码来保存联系方式 ContentValues values new ContentValues values put People NUMBER phone values
  • iPhone:即使设置了另一个语言,NSLocalizedString也会从英语.strings文件中读取

    我有一个应用程序 其中包含一些非美国 Localized strings 文件 它们按照我的预期出现在项目中 有一个 Localized strings 对象 以及 en fr 等的子对象 每个对象都是一个 UTF16 文本文件 并且我已经
  • 在 PAM 模块(.so 文件)的 C 中嵌入 Python 脚本时出现 ImportError 和 PyExc_SystemError

    我正在尝试用 C 编写一个演示 PAM 模块 它使用 C 概念中的嵌入 Python 来运行用 python 2 7 编写的脚本 在 pam sm authenticate 函数内 该函数是用 C 文件 pam auth c 编写的 这是P