使用curl编译PAM模块的对象文件

使用curl编译PAM模块的对象文件,c,gcc,curl,pam,C,Gcc,Curl,Pam,我正在编写一个PAM模块,每次用户登录时我都需要执行https请求。我已经用curl实现了这一点,但问题是一旦我在我的C代码中引入curl include,模块就停止工作了 以下是我用来编译它的命令: gcc-fPIC-fno堆栈保护器-cmypam.c sudo ld-x——shared-o/lib/x86_64-linux-gnu/security/mypam.so mypam.o 它编译时没有问题,但pam模块没有被解释。 如果我删除curl部分,它就可以正常工作(我添加了必要的行以使用m

我正在编写一个PAM模块,每次用户登录时我都需要执行https请求。我已经用curl实现了这一点,但问题是一旦我在我的C代码中引入curl include,模块就停止工作了

以下是我用来编译它的命令:

gcc-fPIC-fno堆栈保护器-cmypam.c

sudo ld-x——shared-o/lib/x86_64-linux-gnu/security/mypam.so mypam.o

它编译时没有问题,但pam模块没有被解释。 如果我删除curl部分,它就可以正常工作(我添加了必要的行以使用
mypam.so

我认为gcc的问题在于我没有表示我想使用CURL。我尝试了
gcc-fPIC-fno stack protector-c mypam.c-lcurl
,但它抱怨:

mypam.c:在函数“pam\u sm\u authenticate”中:
mypam.c:593:2:错误:未知类型名称“pr”

知道发生了什么吗??如果我使用
main
函数将其编译为一个普通程序,并使用命令:
gcc-ggdb-Wall-Wextra-o fo.c-lcrypto-lm-lcurl
,它工作得很好

代码:

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
无效foo(无效){
卷曲*卷曲;
卷曲编码;
curl=curl_easy_init();
//如果我在这里放一个printf(“你好!”),它就行了
}
/*期望钩*/
PAM_EXTERN int PAM_sm_setcred(PAM_handle_t*pamh,int flags,int argc,const char**argv){
返回PAM_成功;
}
PAM_EXTERN int PAM_sm_acct_mgmt(PAM_handle_t*pamh,int flags,int argc,const char**argv){
返回PAM_成功;
}
/*预期的钩子,这是自定义内容发生的地方*/
PAM_EXTERN int PAM_sm_authenticate(PAM_handle_t*pamh,int flags,int argc,const char**argv){
内部检索;
const char*pUsername;
retval=pam_get_user(pamh和pUsername,“用户名:”);
printf(“欢迎%s\n”,pUsername);
foo();
if(retval!=PAM_SUCCESS){
返回返回;
}
返回PAM\u AUTHINFO\u UNAVAIL;
}
正如您所看到的,代码非常简单。如果我只包含curl,它会工作,但如果我引用curl库中的任何内容(如
curl*curl;
它会断开)。 有什么想法吗?
谢谢大家!

首先,您没有链接libpam,所以这将是一个问题。一般来说,我喜欢通过打开dlsym来测试pam模块,然后查找模块希望使用dlsym的符号。这基本上就是pam库在配置pam.conf时所做的。它找到库并打开它并查找给定的符号。下面是一些测试代码,您可以在编译后的pam模块上运行

#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char* argv[])
{
    if ( argc != 2 )
    {
            printf("Usage: ./dlopentest <path_to_pam_module>\n");
            exit(1);
    }
    void *libhandle = dlopen(argv[1], RTLD_NOW);
    if ( libhandle == NULL )
    {
            printf("%s",dlerror());
            exit(1);
    }
    void* sym = dlsym(libhandle,"pam_sm_authenticate");
    if ( sym == NULL )
    {
            printf("%s",dlerror());
            exit(1);
    }
    sym = dlsym(libhandle,"pam_sm_setcred");
    if ( sym == NULL )
    {
            printf("%s",dlerror());
            exit(1);
    }
    dlclose(libhandle);
}
#包括
#包括
#包括
int main(int argc,const char*argv[]
{
如果(argc!=2)
{
printf(“用法:./dlopentest\n”);
出口(1);
}
void*libhandle=dlopen(argv[1],RTLD_NOW);
if(libhandle==NULL)
{
printf(“%s”,dlerror());
出口(1);
}
void*sym=dlsym(libhandle,“pam_sm_authenticate”);
if(sym==NULL)
{
printf(“%s”,dlerror());
出口(1);
}
sym=dlsym(libhandle,“pam_sm_setcred”);
if(sym==NULL)
{
printf(“%s”,dlerror());
出口(1);
}
dlclose(libhandle);
}
显然,并不是所有的pam_sm_*符号都在测试中,只需测试您希望模块具有的符号即可

用-ldl构建并链接它,然后在pam模块共享对象上运行它。在pam.conf中配置模块后,它应该详细地抱怨导致模块无法加载的原因。不过,这非常容易调试,并且可以很容易地合并到单元测试中。我会向任何开发严肃的pam模块的人推荐这种类型的“dlopentest”。

我也有这个问题。 作为一种解决方法,我将cURL相关函数与pam模块分离。 现在pam模块用cURL执行程序并处理结果代码, 比如:


@Wug我用代码更新了帖子。我希望它能有用。对不起,我没有足够的PAM知识来进一步帮助你,希望这段代码能帮助其他比我知道得更多的人。
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char* argv[])
{
    if ( argc != 2 )
    {
            printf("Usage: ./dlopentest <path_to_pam_module>\n");
            exit(1);
    }
    void *libhandle = dlopen(argv[1], RTLD_NOW);
    if ( libhandle == NULL )
    {
            printf("%s",dlerror());
            exit(1);
    }
    void* sym = dlsym(libhandle,"pam_sm_authenticate");
    if ( sym == NULL )
    {
            printf("%s",dlerror());
            exit(1);
    }
    sym = dlsym(libhandle,"pam_sm_setcred");
    if ( sym == NULL )
    {
            printf("%s",dlerror());
            exit(1);
    }
    dlclose(libhandle);
}
char *my_args[5];
pid_t pid;

my_args[0] = "myprogram_with_curl";
my_args[1] = pUsername;
my_args[2] = pPassword;
my_args[3] = NULL;

pid = fork();
int status;
if (pid) //retrieve result from myprogram_with_curl
{
  pid = waitpid(pid, &status, 0);
  if (status != 0)
  {
    return PAM_AUTH_ERR;
  } 
}
else
{
  execv("/usr/bin/myprogram_with_curl", my_args);
  printf("sad! execv failed\n"); 
}