使用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部分,它就可以正常工作(我添加了必要的行以使用使用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
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");
}