/*
 * pam_sshauth: PAM module for authentication via a remote ssh server.
 * Copyright (C) 2010-2013 Scott Balneaves <sbalneav@ltsp.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <syslog.h>
#include <config.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pwd.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>

#include "pam_sshauth.h"

/*
 * create_sshauthdir
 *
 */

int
create_sshauthdir (pam_handle_t * pamh, const char *username)
{
  char *dirname;

  if (asprintf (&dirname, "/tmp/%s.XXXXXX", username) < 0)
    {
      pam_syslog (pamh, LOG_ERR, "Couldn't allocate space to store authdir name");
      return PAM_BUF_ERR;
    }

  if (mkdtemp (dirname) == NULL)
    {
      pam_syslog (pamh, LOG_ERR, "Couldn't generate unique store authdir name");
      return PAM_BUF_ERR;
    }

  return sshauth_pam_env (pamh, SSHAUTHDIR, dirname, CLEANUP);
}

/*
 * askpass_create
 *
 * Create the secure password file needed by the shm_askpass utility.
 */

int
askpass_create (pam_handle_t * pamh)
{
  char *password;
  char *authdir;
  char pw_filename[BUFSIZ];
  int pam_result;
  int f;

  pam_result = pam_get_data (pamh, SSHAUTHDIR, (const void **)&authdir);
  if (pam_result != PAM_SUCCESS)
    {
      pam_syslog (pamh, LOG_ERR, "Couldn't obtain authdir name from the pam stack.");
      return pam_result;
    }

  sprintf (pw_filename, "%s/.passwd", authdir);

  pam_result = pam_get_item (pamh, PAM_AUTHTOK, (const void **)&password);
  if (pam_result != PAM_SUCCESS)
    {
      pam_syslog (pamh, LOG_ERR, "Couldn't obtain PAM_AUTHTOK from the pam stack.");
      return pam_result;
    }

  if ((f = creat (pw_filename, S_IRUSR | S_IWUSR)) < 0)
    {
      pam_syslog (pamh, LOG_ERR, "Couldn't create tmpfile");
      return PAM_SYSTEM_ERR;
    }

  if (write (f, password, strlen (password)) < 0)
    {
      pam_syslog (pamh, LOG_ERR, "Couldn't write to tmpfile");
      return PAM_SYSTEM_ERR;
    }

  close (f);

  return PAM_SUCCESS;
}

/*
 * askpass_remove
 *
 * Remove the password file needed by shm_askpass
 */

int
askpass_remove (pam_handle_t * pamh)
{
  char *authdir;
  char pw_filename[BUFSIZ];
  int pam_result;

  pam_result = pam_get_data (pamh, SSHAUTHDIR, (const void **)&authdir);
  if (pam_result != PAM_SUCCESS)
    {
      pam_syslog (pamh, LOG_ERR, "Couldn't obtain authdir name from the pam stack.");
      return pam_result;
    }

  sprintf (pw_filename, "%s/.passwd", authdir);

  if (unlink (pw_filename) < 0)
    {
      pam_debug (pamh, "tmpfile already removed.");
    }

  return PAM_SUCCESS;
}
