static int unlock(const struct agent_data_t *data, char *password) { if (data->type != AGENT_GPG_AGENT) errx(EXIT_FAILURE, "only gpg-agent supports this operation"); _cleanup_gpg_ struct gpg_t *agent = gpg_agent_connection(data->gpg, NULL); if (!agent) err(EXIT_FAILURE, "failed to connect to GPG_AUTH_SOCK"); if (!password) read_password(&password); const struct fingerprint_t *fgpt = gpg_keyinfo(agent); for (; fgpt; fgpt = fgpt->next) { if (fgpt->flags & KEY_DISABLED) continue; if (gpg_preset_passphrase(agent, fgpt->fingerprint, -1, password) < 0) { warnx("failed to unlock key '%s'", fgpt->fingerprint); return 1; } } return 0; }
/* PAM entry point for authentication verification */ PAM_EXTERN int pam_sm_authenticate(pam_handle_t _unused_ *ph, int _unused_ flags, int _unused_ argc, const char _unused_ **argv) { struct agent_data_t data; const struct passwd *pwd; const char *user, *password; enum agent id = AGENT_DEFAULT; int ret; ret = pam_get_user(ph, &user, NULL); if (ret != PAM_SUCCESS) { syslog(PAM_LOG_ERR, "pam-envoy: couldn't get the user name: %s", pam_strerror(ph, ret)); return PAM_SERVICE_ERR; } pwd = getpwnam(user); if (!pwd) { syslog(PAM_LOG_ERR, "pam-envoy: error looking up user information: %s", strerror(errno)); return PAM_SERVICE_ERR; } /* Look up the password */ ret = pam_get_item(ph, PAM_AUTHTOK, (const void**)&password); if (ret != PAM_SUCCESS || password == NULL) { if (ret == PAM_SUCCESS) syslog(PAM_LOG_WARN, "pam-envoy: no password is available for user"); else syslog(PAM_LOG_WARN, "pam-envoy: no password is available for user: %s", pam_strerror(ph, ret)); return PAM_SUCCESS; } if (pam_get_agent(&data, id, pwd->pw_uid, pwd->pw_gid) < 0) { syslog(PAM_LOG_WARN, "pam-envoy: failed to get agent for user"); return PAM_SUCCESS; } if (data.status == ENVOY_RUNNING && data.type == AGENT_GPG_AGENT) { _cleanup_gpg_ struct gpg_t *agent = gpg_agent_connection(data.gpg); if (password) { const struct fingerprint_t *fpt = gpg_keyinfo(agent); for (; fpt; fpt = fpt->next) { if (gpg_preset_passphrase(agent, fpt->fingerprint, -1, password) < 0) syslog(PAM_LOG_ERR, "failed to unlock '%s'", fpt->fingerprint); } } gpg_close(agent); } return PAM_SUCCESS; }