#include <security/pam_modules.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>

#include <asm/unistd.h>
#include "keyutils.h"


#define PAM_SM_AUTH
#define MAX_V 30

//Copyright 2007 Calculate Pack, http://www.calculate-linux.ru
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
// 
//      http://www.apache.org/licenses/LICENSE-2.0
// 
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.


// 		if (strcmp(arg, "@t" ) == 0) return KEY_SPEC_THREAD_KEYRING;
// 		if (strcmp(arg, "@p" ) == 0) return KEY_SPEC_PROCESS_KEYRING;
// 		if (strcmp(arg, "@s" ) == 0) return KEY_SPEC_SESSION_KEYRING;
// 		if (strcmp(arg, "@u" ) == 0) return KEY_SPEC_USER_KEYRING;
// 		if (strcmp(arg, "@us") == 0) return KEY_SPEC_USER_SESSION_KEYRING;
// 		if (strcmp(arg, "@g" ) == 0) return KEY_SPEC_GROUP_KEYRING;
// 		if (strcmp(arg, "@a" ) == 0) return KEY_SPEC_REQKEY_AUTH_KEY;




//Функция аутенфикации
PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags
                                   ,int argc, const char **argv)
{
// Добавляем если нам нужен файл
// Файл для записи
// char *file="/etc/.tmp";

unsigned int ctrl;
int retval, *ret_data=NULL;;
const char *name, *p;
char *token;


// Достаем имя пользователя
retval = pam_get_user(pamh, &name, "login: ");
if (retval!=PAM_SUCCESS) {return PAM_AUTH_ERR;};

// Структура для пам функций
struct pam_conv *conv;
// Структура для пам сообщений
struct pam_message *pmsg[3],msg[3];
// Структура для храения ответов пам
struct pam_response *response;
// Получаем функцию для доставания пароля
retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv );

if (retval!=PAM_SUCCESS) {return PAM_AUTH_ERR;}

int flag = 0;
     for (ctrl=0; argc-- > 0; ++argv) 
     {
       if (!strcmp(*argv,"use_first_pass"))
       {
         retval = pam_get_item(pamh,PAM_AUTHTOK,(const void **)&p);
         if (retval!=PAM_SUCCESS) {return PAM_AUTH_ERR;};
         flag = 1;
       };
     };
if (flag == 0){

  //Инициализируем структуру сообщений
  pmsg[0] = &msg[0];
  msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
  msg[0].msg="Password:";
  //Получаем указатель на ответ пама
  retval = conv->conv(1, ( const struct pam_message ** ) pmsg, &response, conv->appdata_ptr);

  if (retval!=PAM_SUCCESS) {return PAM_AUTH_ERR;};
  //Получаем password
  p = response->resp;
 };

//Если пользователь root то не пишем файл
if (strcmp(name,"root")){
// Добавляем если нам нужен файл
//Создаем файл с правами 0777 и записываем в него информацию 
//   FILE *fp;
//   fp=fopen (file,"w");
//   if (fp!=NULL){fprintf (fp, "%s\n", p); chmod (file,0600);}
//   fclose(fp);

  key_serial_t dest;
  int ret;
  // Получаем id пользовательског ключа
  dest = KEY_SPEC_USER_SESSION_KEYRING;
  //printf("DEST=%d\n",dest);

  // записываем ключ в пространство root
  ret = add_key("user", name, p, strlen(p), dest);
  }

//Копируем password для передачи следующему модулю
token = strdup(p);
p=NULL;
// Передаем password cледующему модулю
retval = pam_set_item (pamh, PAM_AUTHTOK, (const void *) token);

if (retval == PAM_SUCCESS) {return PAM_SUCCESS;}
        return PAM_AUTH_ERR;
}


// Функция ничего не делает но нужна для корректной работы
PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags
                              ,int argc, const char **argv)
{
        unsigned int ctrl;
        int retval;


        retval = PAM_SUCCESS;

        return retval;
}

#ifdef PAM_STATIC
struct pam_module _pam_unix_auth_modstruct = {
    "pam_permit",
    pam_sm_authenticate,
    pam_sm_setcred,
    NULL,
    NULL,
    NULL,
    NULL,
};
#endif
 
