+struct passwd *
+sshpam_getpw(const char *user)
+{
+ struct passwd *pw;
+
+ if ((pw = getpwnam(user)) != NULL)
+ return(pw);
+
+ debug("PAM: faking passwd struct for user '%.100s'", user);
+ if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)
+ return NULL;
+ pw->pw_name = xstrdup(user); /* XXX leak */
+ pw->pw_shell = "/bin/true";
+ pw->pw_gecos = "sshd fake PAM user";
+ return (pw);
+}
+
+void
+sshpam_check_userchanged(void)
+{
+ int sshpam_err;
+ struct passwd *pw;
+ const char *user;
+
+ debug("sshpam_check_userchanged");
+ sshpam_err = pam_get_item(sshpam_handle, PAM_USER, &user);
+ if (sshpam_err != PAM_SUCCESS)
+ fatal("PAM: could not get PAM_USER: %s",
+ pam_strerror(sshpam_handle, sshpam_err));
+ if (strcmp(user, sshpam_authctxt->pw->pw_name) != 0) {
+ debug("PAM: user mapped from '%.100s' to '%.100s'",
+ sshpam_authctxt->pw->pw_name, user);
+ if ((pw = getpwnam(user)) == NULL)
+ fatal("PAM: could not get passwd entry for user "
+ "'%.100s' provided by PAM_USER", user);
+ pwfree(sshpam_authctxt->pw);
+ sshpam_authctxt->pw = pw;
+ sshpam_authctxt->valid = allowed_user(pw);
+ debug("PAM: user '%.100s' now %svalid", user,
+ sshpam_authctxt->valid ? "" : "in");
+ }
+}
+
+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, *user;
+ 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));
+ if (options.permit_pam_user_change) {
+ user = buffer_get_string(b, NULL);
+ debug("PAM: got username '%.100s' from thread", user);
+ if ((err = pam_set_item(sshpam_handle, PAM_USER, user)) != PAM_SUCCESS)
+ fatal("PAM: failed to set PAM_USER: %s",
+ pam_strerror(sshpam_handle, err));
+ pwfree(sshpam_authctxt->pw);
+ sshpam_authctxt->pw = pwcopy(sshpam_getpw(user));
+ }
+
+ /* 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));
+ }
+#endif
+ }
+#endif
+}