最近在网上找了不少关于pam的资料,虽然很多,但是都只是动态交互进行验证。因为工作需要,需要进行静态的验证,于是写了如下代码。以下在Mac os X上验证通过。如果把#include <pam/pam_appl.h>,#include <pam/pam_misc.h>,改成#include <security/pam_appl.h>,#include <security/pam_misc.h>应该直接可以在Linux,和Unix等支持Posix标准的环境下运行。
#include <sys/param.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/wait.h>
#include <err.h> #include <errno.h> #include <grp.h> #include <paths.h> #include <pwd.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <syslog.h> #include <unistd.h>
#include <pam/pam_appl.h> #include <pam/pam_misc.h> //#include <pam/pam_misc.h>
int su_conv(int num_msg, const struct pam_message **msgm, //回调函数,非常重要!!!! struct pam_response **response,void *appdata_ptr);
//static struct pam_conv conv = {misc_conv,NULL};
int main (int argc, const char * argv[]) { // insert code here... pam_handle_t *pamh; const char* mytty,*p; char *password = "718412"; char *user = "root"; struct pam_conv conv = {su_conv, password}; //其中password就是直接传递给su_conv回调函数void *appdata_ptr 指针 int retval = 100; printf("uid: %d\n", getuid()); retval = pam_start("su","root",&conv,&pamh); if(retval = PAM_SUCCESS) //pam_get_item(pamh,PAM_USER,(const void **)&p); pam_set_item(pamh,PAM_CONV, getlogin());
mytty = ttyname(STDERR_FILENO); if (!mytty) mytty = "tty"; pam_set_item(pamh,PAM_TTY, mytty);
retval = pam_authenticate(pamh,PAM_SILENT); printf("return code: %d\n", retval); if(retval != PAM_SUCCESS) { printf("invalid password\n"); return -1; } retval = pam_end(pamh,PAM_SUCCESS); printf("uid: %d\n", getuid()); setuid(0); printf("uid: %d\n", getuid()); printf("the retval is now %d",retval); return 0; }
int su_conv(int num_msg, const struct pam_message **msgm, struct pam_response **response, void *appdata_ptr) {
char *rec; struct pam_message *m = (struct pam_message *)*msgm; struct pam_response *r; while(num_msg--) { switch(m->msg_style) { case PAM_PROMPT_ECHO_OFF: // r->resp = strdup(getpass(m->msg)); r = (struct pam_response *)malloc(sizeof(struct pam_response)); r->resp = (char *)malloc(100); r->resp_retcode = 0; strcpy(r->resp, appdata_ptr); *response = r; break; case PAM_PROMPT_ECHO_ON: //r->resp = (char *)getpass(m->msg); //fprintf(stdout,"%s",m->msg); r->resp = malloc(PAM_MAX_RESP_SIZE); fgets(r->resp,PAM_MAX_RESP_SIZE,stdin); //gets(rec); break; case PAM_ERROR_MSG: (void)fputs(m->msg,stdout); break; case PAM_TEXT_INFO: fprintf(stdout,"%s\n",m->msg); break; default: break; } } return PAM_SUCCESS; } 
|