#include <pthread.h>
#include <sys/stat.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>

#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <security/pam_ext.h>

#include <pwd.h>

PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) {
    return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) {
    return PAM_SUCCESS;
}

PAM_EXTERN int pam_sm_authenticate( pam_handle_t *pamh, int flags,int argc, const char **argv ) {

/**************** Read informations ******************/

    // start syslog channel
    setlogmask (LOG_UPTO (LOG_NOTICE));
    openlog ("etap", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);

    // fetch username
    const char* user;
    pam_get_user(pamh,&user,NULL);

    // fetch user uid
    struct passwd *pw;
    pw = getpwnam(user);
    uid_t uid = pw->pw_uid;

/**************** User directory ******************/

    // create user directory
    char dir_path[1024];
    sprintf(dir_path, "/run/etap/%d", uid);
    mkdir(dir_path, 0700);
    chown(dir_path, uid, 0);
    syslog (LOG_NOTICE, "dir %s", dir_path);

/**************** helper ******************/

    // run helper
    if(strcmp(user,"root") != 0){
        // write helper file
        FILE *helperfile = fopen("/run/etap/helper-user", "w");
        if(helperfile != NULL){
            fprintf(helperfile, "%s", user);
            fclose(helperfile);
        }
        syslog (LOG_NOTICE, "wine helper :%s", user);
        int status = system("/usr/libexec/wineprefix-helper");
        if(status != 0){
            syslog (LOG_NOTICE, "wine helper failed: %s %d", user, status);
        }
        closelog ();
    }

/**************** auth ******************/

    // accept all passwords for ogrenci
    if(strcmp(user,"ogrenci")==0){
        return PAM_SUCCESS;
    }

    // check auto user file
    FILE *userfile = fopen("/run/etap/user", "r");
    char autouser[128];
    if(userfile == NULL) {
        syslog (LOG_NOTICE, "skip autouser: %s", user);
        closelog ();
        return PAM_AUTH_ERR;
    } else {
        size_t readed = fread(autouser, sizeof(char), 128, userfile);
        fclose(userfile);
        unlink("/run/etap/user");
        if(readed == 0) {
            syslog (LOG_NOTICE, "read error: %s", user);
            closelog ();
            return PAM_AUTH_ERR;
        }
    }
    // accept if autouser check success
    syslog (LOG_NOTICE, "autouser %s: user:%s", autouser, user);
    if(strncmp(user,autouser, strlen(user))==0){
        syslog (LOG_NOTICE, "success %s:%s", autouser, user);
        closelog ();
        return PAM_SUCCESS;
    }

/**************** Done ******************/

    closelog ();
    return PAM_AUTH_ERR;
}

PAM_EXTERN int pam_sm_setcred( pam_handle_t *pamh, int flags,int argc, const char **argv ) {
    return PAM_SUCCESS;
}
