#include #include #include #include #include #include #include #include #include #include #include #include #define PAMPY "python3 /usr/bin/pam_mfa.py" int request_mfa(pam_handle_t *pamh, const char *user, const char *service, char* result) { FILE *fp; int cmdsize = 256; int result_size = 2; // Build command line char cmd[cmdsize]; cmd[0] = '\0'; strcat(cmd, PAMPY); strcat(cmd," --user "); strcat(cmd,user); strcat(cmd," --service "); strcat(cmd,service); pam_syslog(pamh,LOG_INFO,cmd); // Execute pam.py if ((fp = popen(cmd,"r")) == NULL) { pam_syslog(pamh,LOG_ERR,"Error opening pipe"); result = "1"; return 1; } // Set result to output of pam_mfa.py fgets(result,result_size,fp); pclose(fp); return 0; } int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char** argv) { const char *user; const char *service; // Get user and service if (pam_get_item(pamh, PAM_USER, (const void **) &user) != PAM_SUCCESS || user == NULL) { pam_syslog(pamh,LOG_ERR,"unable to get user"); return PAM_AUTHINFO_UNAVAIL; } if (pam_get_item(pamh, PAM_SERVICE, (const void **) &service) != PAM_SUCCESS || service == NULL) { pam_syslog(pamh,LOG_ERR,"unable to get service"); return PAM_AUTHINFO_UNAVAIL; } int retval; int result_size = 2; char result[result_size]; if ((retval = request_mfa(pamh, user, service, result)) != 0) { pam_syslog(pamh,LOG_ERR,"error performing mfa"); return PAM_AUTH_ERR; } if (atoi(result) == 0) { pam_syslog(pamh,LOG_INFO,"auth success"); return PAM_SUCCESS; } else { pam_syslog(pamh,LOG_ERR,"auth error"); return PAM_AUTH_ERR; } } int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char** argv) { if (flags & PAM_DELETE_CRED || flags & PAM_REFRESH_CRED || flags & PAM_ESTABLISH_CRED) { return PAM_SUCCESS; } if (flags & PAM_REINITIALIZE_CRED) { int retval = pam_sm_authenticate(pamh,flags,argc,argv); if (retval == PAM_SUCCESS) { return PAM_SUCCESS; } else { return PAM_CRED_ERR; } } }