int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { if (flags == PAM_ESTABLISH_CRED) return pam_sm_open_session(pamh, flags, argc, argv); return PAM_SUCCESS; }
int main(int argc, char **argv) { int i, ret, abi_flag, pargc; const char *user, *service, *authtok, *old_authtok, **pargv; char **envlist; struct passwd *pwd; struct pam_conv conv; pam_handle_t *pamh; if (argc < 2) { fprintf(stderr, "Usage: %s [flags]\n" "\t--debug\n" "\t--toggle-abi\n" "\t--setservice SERVICE\n" "\t--setuser USER\n" "\t--setauthtok AUTHTOK\n" "\t--setoldauthtok OLD_AUTHTOK\n" "\t--restart\n" "\t--run [cmd]\n" "\t--auth [args...]\n" "\t--open-session [args...]\n" "\t--setcred-establish [args...]\n" "\t--setcred-reinitialize [args...]\n" "\t--setcred-delete [args...]\n" "\t--close-session [args...]\n" "\t--acct-mgmt [args...]\n" "\t--chauthtok-prelim [args...]\n" "\t--chauthtok-update [args...]\n", argv[0]); return 1; } pwd = getpwuid(getuid()); if (pwd == NULL) { fprintf(stderr, "Unable to determine name of current user!\n"); return 1; } user = pwd->pw_name; service = "login"; authtok = NULL; old_authtok = NULL; ret = 0; pamh = NULL; memset(&conv, 0, sizeof(conv)); conv.conv = local_conv; abi_flag = 0; conv.appdata_ptr = &abi_flag; pargc = 0; pargv = NULL; for (i = 1; i < argc; i++) { fflush(stdout); if (strcmp(argv[i], "--debug") == 0) { log_options.debug++; continue; } if (strcmp(argv[i], "--toggle-abi") == 0) { abi_flag = !abi_flag; continue; } if (strcmp(argv[i], "--setservice") == 0) { service = argv[i + 1]; i++; continue; } if (strcmp(argv[i], "--setuser") == 0) { user = argv[i + 1]; i++; continue; } if (strcmp(argv[i], "--setauthtok") == 0) { authtok = argv[i + 1]; i++; continue; } if (strcmp(argv[i], "--setoldauthtok") == 0) { old_authtok = argv[i + 1]; i++; continue; } if (pamh == NULL) { ret = pam_start(service, user, &conv, &pamh); printf("start: %d\n", ret); #ifdef __LINUX_PAM__ /* Linux-PAM *actively* tries to break us. */ ((struct linux_pam_handle*)pamh)->caller = 1; #endif if (authtok != NULL) { ret = pam_set_item(pamh, PAM_AUTHTOK, authtok); printf("set authtok: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); } if (old_authtok != NULL) { ret = pam_set_item(pamh, PAM_OLDAUTHTOK, old_authtok); printf("set old authtok: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); } } if (strcmp(argv[i], "--restart") == 0) { #ifdef __LINUX_PAM__ /* Linux-PAM *actively* tries to break us. */ ((struct linux_pam_handle*)pamh)->caller = 2; #endif ret = pam_end(pamh, 0); printf("end: %d\n", ret); pamh = NULL; ret = pam_start(service, user, &conv, &pamh); printf("start: %d\n", ret); #ifdef __LINUX_PAM__ /* Linux-PAM *actively* tries to break us. */ ((struct linux_pam_handle*)pamh)->caller = 1; #endif continue; } if (strcmp(argv[i], "--auth") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_authenticate(pamh, 0, pargc, pargv); free_args(&pargc, &pargv); printf("authenticate: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--run") == 0) { envlist = pam_getenvlist(pamh); if (envlist != NULL) { while (*envlist != NULL) { putenv(*envlist); envlist++; } } ret = system(argv[i + 1]); printf("run(\"%s\"): %d%s %s\n", argv[i + 1], WEXITSTATUS(ret), WEXITSTATUS(ret) ? ":" : "", WEXITSTATUS(ret) ? strerror(WEXITSTATUS(ret)) : ""); i++; continue; } if (strcmp(argv[i], "--open-session") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_open_session(pamh, 0, pargc, pargv); free_args(&pargc, &pargv); printf("open session: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--setcred-establish") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_setcred(pamh, PAM_ESTABLISH_CRED, pargc, pargv); free_args(&pargc, &pargv); printf("setcred: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--setcred-reinitialize") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_setcred(pamh, PAM_REINITIALIZE_CRED, pargc, pargv); free_args(&pargc, &pargv); printf("setcred: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--setcred-delete") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_setcred(pamh, PAM_DELETE_CRED, pargc, pargv); free_args(&pargc, &pargv); printf("setcred: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--close-session") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_close_session(pamh, 0, pargc, pargv); free_args(&pargc, &pargv); printf("close session: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--acct-mgmt") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_acct_mgmt(pamh, 0, pargc, pargv); free_args(&pargc, &pargv); printf("acct mgmt: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--chauthtok-prelim") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_chauthtok(pamh, PAM_PRELIM_CHECK, pargc, pargv); free_args(&pargc, &pargv); printf("chauthtok-prelim: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } if (strcmp(argv[i], "--chauthtok-update") == 0) { i += gather_args(argc, argv, i + 1, &pargc, &pargv); ret = pam_sm_chauthtok(pamh, PAM_UPDATE_AUTHTOK, pargc, pargv); free_args(&pargc, &pargv); printf("chauthtok-update: %d%s %s\n", ret, ret ? ":" : "", ret ? pam_strerror(pamh, ret) : ""); continue; } fprintf(stderr, "Unrecognized argument: %s\n", argv[i]); break; } if (pamh != NULL) { #ifdef __LINUX_PAM__ /* Linux-PAM *actively* tries to break us. */ ((struct linux_pam_handle*)pamh)->caller = 2; #endif ret = pam_end(pamh, 0); printf("end: %d\n", ret); pamh = NULL; } return ret; }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { pam_syslog(pamh, LOG_INFO, "pam_sm_authenticate\n"); if (get_env(pamh, "PAM_KWALLET_LOGIN") != NULL) { pam_syslog(pamh, LOG_INFO, "pam_kwallet: we were already executed"); return PAM_SUCCESS; } parseArguments(argc, argv); int result; //Fetch the user, needed to get user information const char *username; result = pam_get_user(pamh, &username, NULL); if (result != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "pam_kwallet: Couldn't get username %s", pam_strerror(pamh, result)); return PAM_IGNORE;//Since we are not an essential module, just make pam ignore us } struct passwd *userInfo; userInfo = getpwnam(username); if (!userInfo) { pam_syslog(pamh, LOG_ERR, "pam_kwallet: Couldn't get user info (passwd) info"); return PAM_IGNORE; } const char *password; result = pam_get_item(pamh, PAM_AUTHTOK, (const void**)&password); if (result != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "pam_kwallet: Couldn't get password %s", pam_strerror(pamh, result)); return PAM_IGNORE; } if (!password) { pam_syslog(pamh, LOG_NOTICE, "pam_kwallet: Couldn't get password (it is empty)"); //Asking for the password ourselves result = prompt_for_password(pamh); if (result != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "pam_kwallet: Prompt for password failed %s", pam_strerror(pamh, result) ); return PAM_IGNORE; } } //even though we just set it, better check to be 100% sure result = pam_get_item(pamh, PAM_AUTHTOK, (const void**)&password); if (result != PAM_SUCCESS || !password) { pam_syslog(pamh, LOG_ERR, "pam_kwallet: Password is not there even though we set it %s", pam_strerror(pamh, result)); return PAM_IGNORE; } char *key = malloc(sizeof(char) * KWALLET_PAM_KEYSIZE); if (kwallet_hash(password, userInfo, key) != 0) { pam_syslog(pamh, LOG_ERR, "pam_kwallet: Fail into creating the hash"); return PAM_IGNORE; } result = pam_set_data(pamh, "kwallet_key", key, NULL); if (result != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "pam_kwallet: Impossible to store the hashed password: %s" , pam_strerror(pamh, result)); return PAM_IGNORE; } //if sm_open_session has already been called (but we did not have password), call it now const char *session_bit; result = pam_get_data(pamh, "sm_open_session", (const void **)&session_bit); if (result == PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "pam_kwallet: open_session was called before us, calling it now"); return pam_sm_open_session(pamh, flags, argc, argv); } //TODO unlock kwallet that is already executed return PAM_SUCCESS; }