- struct pam_response *reply;
- int count;
- char buf[1024];
-
- /* PAM will free this later */
- reply = xmalloc(num_msg * sizeof(*reply));
-
- for (count = 0; count < num_msg; count++) {
- if (pamstate == INITIAL_LOGIN) {
- /*
- * We can't use stdio yet, queue messages for
- * printing later
- */
- switch(PAM_MSG_MEMBER(msg, count, msg_style)) {
- case PAM_PROMPT_ECHO_ON:
- xfree(reply);
- return PAM_CONV_ERR;
- case PAM_PROMPT_ECHO_OFF:
- if (__pampasswd == NULL) {
- xfree(reply);
- return PAM_CONV_ERR;
- }
- reply[count].resp = xstrdup(__pampasswd);
- reply[count].resp_retcode = PAM_SUCCESS;
- break;
- case PAM_ERROR_MSG:
- case PAM_TEXT_INFO:
- if (PAM_MSG_MEMBER(msg, count, msg) != NULL) {
- message_cat(&__pam_msg,
- PAM_MSG_MEMBER(msg, count, msg));
- }
- reply[count].resp = xstrdup("");
- reply[count].resp_retcode = PAM_SUCCESS;
- break;
- default:
- xfree(reply);
- return PAM_CONV_ERR;
- }
- } else {
- /*
- * stdio is connected, so interact directly
- */
- switch(PAM_MSG_MEMBER(msg, count, msg_style)) {
- case PAM_PROMPT_ECHO_ON:
- fputs(PAM_MSG_MEMBER(msg, count, msg), stderr);
- fgets(buf, sizeof(buf), stdin);
- reply[count].resp = xstrdup(buf);
- reply[count].resp_retcode = PAM_SUCCESS;
- break;
- case PAM_PROMPT_ECHO_OFF:
- reply[count].resp =
- read_passphrase(PAM_MSG_MEMBER(msg, count,
- msg), RP_ALLOW_STDIN);
- reply[count].resp_retcode = PAM_SUCCESS;
- break;
- case PAM_ERROR_MSG:
- case PAM_TEXT_INFO:
- if (PAM_MSG_MEMBER(msg, count, msg) != NULL)
- fprintf(stderr, "%s\n",
- PAM_MSG_MEMBER(msg, count, msg));
- reply[count].resp = xstrdup("");
- reply[count].resp_retcode = PAM_SUCCESS;
- break;
- default:
- xfree(reply);
- return PAM_CONV_ERR;
- }
+ int result;
+
+ if (sshpam_authctxt == NULL)
+ fatal("PAM: sshpam_authctxt not initialized");
+ if (setreuid(sshpam_authctxt->pw->pw_uid, -1) == -1)
+ fatal("%s: setreuid failed: %s", __func__, strerror(errno));
+ result = pam_chauthtok(pamh, flags);
+ if (setreuid(0, -1) == -1)
+ fatal("%s: setreuid failed: %s", __func__, strerror(errno));
+ return result;
+}
+# define pam_chauthtok(a,b) (sshpam_chauthtok_ruid((a), (b)))
+#endif
+
+void
+sshpam_password_change_required(int reqd)
+{
+ debug3("%s %d", __func__, reqd);
+ if (sshpam_authctxt == NULL)
+ fatal("%s: PAM authctxt not initialized", __func__);
+ sshpam_authctxt->force_pwchange = reqd;
+ if (reqd) {
+ no_port_forwarding_flag |= 2;
+ no_agent_forwarding_flag |= 2;
+ no_x11_forwarding_flag |= 2;
+ } else {
+ no_port_forwarding_flag &= ~2;
+ no_agent_forwarding_flag &= ~2;
+ no_x11_forwarding_flag &= ~2;
+ }
+}
+
+/* Import regular and PAM environment from subprocess */
+static void
+import_environments(Buffer *b)
+{
+ char *env;
+ u_int i, num_env;
+ int err;
+
+ debug3("PAM: %s entering", __func__);
+
+#ifndef UNSUPPORTED_POSIX_THREADS_HACK
+ /* Import variables set by do_pam_account */
+ sshpam_account_status = buffer_get_int(b);
+ sshpam_password_change_required(buffer_get_int(b));
+
+ /* Import environment from subprocess */
+ num_env = buffer_get_int(b);
+ if (num_env > 1024)
+ fatal("%s: received %u environment variables, expected <= 1024",
+ __func__, num_env);
+ sshpam_env = xcalloc(num_env + 1, sizeof(*sshpam_env));
+ debug3("PAM: num env strings %d", num_env);
+ for(i = 0; i < num_env; i++)
+ sshpam_env[i] = buffer_get_string(b, NULL);
+
+ sshpam_env[num_env] = NULL;
+
+ /* Import PAM environment from subprocess */
+ num_env = buffer_get_int(b);
+ debug("PAM: num PAM env strings %d", num_env);
+ for(i = 0; i < num_env; i++) {
+ env = buffer_get_string(b, NULL);
+
+#ifdef HAVE_PAM_PUTENV
+ /* Errors are not fatal here */
+ if ((err = pam_putenv(sshpam_handle, env)) != PAM_SUCCESS) {
+ error("PAM: pam_putenv: %s",
+ pam_strerror(sshpam_handle, sshpam_err));