我正在编写PAM模块,每次用户登录时我都需要执行https请求。我已经使用curl实现了,但问题是我只要在我的C代码中引入curl include,模块停止工作。
以下是我用来编译它的命令:
gcc -fPIC -fno-stack-protector -c mypam.c
sudo ld -x --shared -o /lib/x86_64-linux-gnu/security/mypam.so mypam.o
它编译没有问题,但pam模块没有被解释。
如果我删除卷曲部分它工作正常(我添加了必要的行使用mypam.so
)
我认为问题在于gcc,我并没有表明我想要使用CURL。我试过了gcc -fPIC -fno-stack-protector -c mypam.c -lcurl
,但它抱怨道:
mypam.c: In function ‘pam_sm_authenticate’:
mypam.c:593:2: error: unknown type name ‘pr’
知道发生了什么事吗?如果我使用main
函数将其编译为普通程序并使用命令:gcc -ggdb -Wall -Wextra -o fo fo.c -lcrypto -lm -lcurl
它可以正常工作。
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <curl/curl.h>
void foo(void){
CURL *curl;
CURLcode res;
curl = curl_easy_init();
// If I just put here a printf("Hello!"); it works
}
/* expected hook */
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;
}
/* expected hook, this is where custom stuff happens */
PAM_EXTERN int pam_sm_authenticate( pam_handle_t *pamh, int flags,int argc, const char **argv ) {
int retval;
const char* pUsername;
retval = pam_get_user(pamh, &pUsername, "Username: ");
printf("Welcome %s\n", pUsername);
foo();
if (retval != PAM_SUCCESS) {
return retval;
}
return PAM_AUTHINFO_UNAVAIL;
}
正如您所看到的,代码非常简单。如果我只包括curl它可以工作,但如果我在curl库中引用任何东西(因为CURL *curl;
它会中断)。
任何的想法?
谢谢!
答案 0 :(得分:0)
嗯,你没有用libpam链接一件事,所以这将成为一个问题。一般来说,我喜欢通过倾斜测试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);
}
显然并非所有的pam_sm_ *符号都经过测试,只需测试您希望模块具有的那些符号。
使用-ldl构建并链接它,然后在pam模块共享对象上运行它。在pam.conf中配置模块后,它应该详细地抱怨导致模块无法加载的任何内容。这非常容易调试,并且可以很容易地结合到单元测试中。我会向正在开发一个严重的pam模块的人推荐这种“dlopentest”。
答案 1 :(得分:0)
我也有这个问题。 作为一种解决方法,我将我的cURL相关函数与pam模块分开。 现在,pam模块使用cURL执行程序并处理结果代码, 像:
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");
}