diff --git a/authKeysPg.c b/authKeysPg.c index 3739577..13de43b 100644 --- a/authKeysPg.c +++ b/authKeysPg.c @@ -10,34 +10,21 @@ #define BDD_PASS_FILE "/srv/bdd/pipi-system.pass" #define BDD_CONN_LENGTH 255 -static void -exit_nicely(PGconn *conn) -{ - PQfinish(conn); - exit(1); -} int main(int argc, char **argv) { - - PGconn *conn; - PGresult *res; - int nFields; - - int j,i; - - errno=0; - - /* Crée une connexion à la base de données */ - char connInfo[BDD_CONN_LENGTH] = "dbname='pipi' user=pipisys password='"; - char lastAp = '\''; FILE *dbPassFile; char ch; int pos = strlen(connInfo); + + PGconn *conn; + PGresult *res; + int i; + // Récupère le mdp à la BDD dbPassFile = fopen(BDD_PASS_FILE,"r"); if (dbPassFile == NULL) { fprintf(stderr,"Cannot open file %s, on peut pas se connecter à la base de données pour lister les clés en tant que %d -> fopen error %d\n", BDD_PASS_FILE,geteuid(),errno); @@ -51,53 +38,43 @@ main(int argc, char **argv) fclose(dbPassFile); connInfo[pos] = '\''; - + // Connecte à la BDD conn = PQconnectdb(connInfo); - - /* Vérifier que la connexion au backend a été faite avec succès */ if (PQstatus(conn) != CONNECTION_OK) { fprintf(stderr, "Connection to database failed: %s", PQerrorMessage(conn)); - exit_nicely(conn); + PQfinish(conn); return 1; } - - /* Initialise un search path sûr, pour qu'un utilisateur - malveillant ne puisse prendre le contrôle. */ res = PQexec(conn, "SELECT pg_catalog.set_config('search_path', '', false)"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { fprintf(stderr, "SET failed: %s", PQerrorMessage(conn)); PQclear(res); - exit_nicely(conn); + PQfinish(conn); + return 1; } - - /* - * Il faut libérer PGresult avec PQclear dès que l'on en a plus besoin pour - * éviter les fuites de mémoire. - */ PQclear(res); - //res = PQprepare(conn,"GettingAllLoginGitUsersInfo","SELECT * FROM $1",1,NULL); - //const char * tablename = "git-users"; - //res = PQexecPrepared(conn,"GettingAllLoginGitUsersInfo",1,"git-users",NULL,NULL,0); - - res = PQexec(conn,"SELECT \"userID\",\"sshKeyType\",\"sshPubKey\" FROM git.keys"); - /* affiche d'abord les noms des attributs */ - nFields = PQnfields(res); - - fprintf(stderr, PQerrorMessage(conn)); - /* puis affiche les lignes */ + + // Demande les données à la BDD + res = PQexec(conn,"SELECT \"sshKeyType\",\"sshPubKey\" FROM git.keys"); + if (PQresultStatus(res) != PGRES_TUPLES_OK) { + fprintf(stderr,"Impossible de lancer la requête SQL pour les autorisations: %s",PQerrorMessage(conn)); + PQclear(res); + PQfinish(conn); + return 1; + } + + // Renvoie le résultat à travers stdout for (i = 0; i < PQntuples(res); i++) { - printf("%s %s\n",PQgetvalue(res,i,1),PQgetvalue(res,i,2)); + printf("%s %s\n",PQgetvalue(res,i,0),PQgetvalue(res,i,1)); } - PQclear(res); - fprintf(stderr,"La liste des clés a été envoyée\n"); - /* ferme la connexion à la base et nettoie */ + PQclear(res); PQfinish(conn); return 0; } diff --git a/bash-gitonly.c b/bash-gitonly.c index 68ca91e..3088b97 100644 --- a/bash-gitonly.c +++ b/bash-gitonly.c @@ -148,6 +148,7 @@ int main(int argc, char **argv, char **envp){ ERR("Impossible de lancer la requête SQL pour les autorisations: %s",PQerrorMessage(conn)); PQclear(res); nargv_free(gitargv); + PQfinish(conn); return 1; } diff --git a/pam_oath_key.c b/pam_oath_key.c index b60eca0..d500d1d 100644 --- a/pam_oath_key.c +++ b/pam_oath_key.c @@ -11,25 +11,22 @@ #include //Pour la conversion bigendian/littleendian -// These #defines must be present according to PAM documentation. +// Qu'es-ce qui est défini #define PAM_SM_AUTH -//#define PAM_SM_ACCOUNT -//#define PAM_SM_SESSION -//#define PAM_SM_PASSWORD - +#include #include #include +#include +#include // Les fonctions de debug -#define D(x) do {\ - printf("[%s:%s(%d)] ", __FILE__, __FUNCTION__, __LINE__);\ - printf x;\ - printf("\n");\ -} while (0) -#define DBG(x) if (cfg.debug) {\ - D(x);\ +#define D(...) \ + pam_syslog(pamh, LOG_NOTICE, ##__VA_ARGS__); + +#define DBG(...) if(cfg.debug) {\ + pam_syslog(pamh, LOG_NOTICE, ##__VA_ARGS__);\ } #define PAM_EXTERN extern @@ -62,10 +59,10 @@ static void copyUntilEndline(const char * src, char dest[]){ } static void -parse_cfg(int flags, int argc, - const char ** argv, struct cfg * cfg) { +parse_cfg(pam_handle_t * pamh, int flags, int argc, const char ** argv, struct cfg * cfg) { + int i; - + cfg -> debug = 1; cfg -> digits = 6; cfg -> window = 5; @@ -80,17 +77,17 @@ parse_cfg(int flags, int argc, } if (MIN_OTP_LEN > cfg -> digits || cfg -> digits > MAX_OTP_LEN) { - D(("La longueur du code otp doit être entre %i et %i. Valeur invalide: digits=%i",MIN_OTP_LEN,MAX_OTP_LEN, cfg -> digits)); + D("La longueur du code otp doit être entre %i et %i. Valeur invalide: digits=%i",MIN_OTP_LEN,MAX_OTP_LEN, cfg -> digits); } if (cfg -> debug) { - D(("called.")); - D(("flags %d argc %d", flags, argc)); + D("called."); + D("flags %d argc %d", flags, argc); for (i = 0; i < argc; i++) - D(("argv[%d]=%s", i, argv[i])); - D(("debug=%d", cfg -> debug)); - D(("digits=%d", cfg -> digits)); - D(("window=%d", cfg -> window)); + D("argv[%d]=%s", i, argv[i]); + D("debug=%d", cfg -> debug); + D("digits=%d", cfg -> digits); + D("window=%d", cfg -> window); } } @@ -99,7 +96,7 @@ char * strtokk(char * str,const char cutter) { while((*str != cutter) && (*str != '\0')) str++; - bool strEnd = (*str == '\0'); + int strEnd = (*str == '\0'); *str = '\0'; if(!strEnd) str++; @@ -131,7 +128,6 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv int retval, rc; - const char * user = NULL; const char * password = NULL; char otp[MAX_OTP_LEN + 1]; int password_len = 0; @@ -145,75 +141,69 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv PGconn *conn; PGresult *res; int nFields; + + const char * ssh_auth_info_ret; + char ssh_auth_info [SSH_AUTH_INFO_LEN]; + int gitUserID; char * oathSecret; + + char * authType; + char * sshKeyType; + char * sshKeyVal; + + char connInfo[BDD_CONN_LENGTH] = "dbname='pipi' user=pipisys password='"; + FILE *dbPassFile; + int pos = strlen(connInfo); + + const char *paramValues[2]; + + char oathSecretBin[OTP_SECRET_LEN]; + int oathSecretBinLen = OTP_SECRET_LEN+1; + + //GIT_USERID=######## + char envStr[11+8]; - FILE* stderr2 = fopen("/tmp/pam-oath.log","w"); - - D(("Running the oath authenticator !\n")); - fprintf(stderr2,"Ca a au moins passé l'init ...\n"); + D("Running the oath authenticator !\n"); - /***** Parsing config *****/ - parse_cfg(flags, argc, argv, & cfg); + parse_cfg(pamh, flags, argc, argv, &cfg); - /***** Getting User *****/ - retval = pam_get_user(pamh, &user, NULL); - if (retval != PAM_SUCCESS) { - DBG(("Could not get PAM user: %s", pam_strerror(pamh, retval))); - goto done; - } - DBG(("We got the user: %s", user)); - fprintf(stderr2,"Le user est là ! %s\n", user); - - /****** Getting ssh key ******/ + /****** Retrieve SSH authentication information. ******/ + ssh_auth_info_ret = pam_getenv(pamh, "SSH_AUTH_INFO_0"); - /* Retrieve SSH authentication information. */ - const char * ssh_auth_info_ret = pam_getenv(pamh, "SSH_AUTH_INFO_0"); - char ssh_auth_info [SSH_AUTH_INFO_LEN]; - ssh_auth_info_ret = "pubkey ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILNTOkgZXdTFzWOC9R1Aeuq30B3lG+Eq8nL76tZsJ9Qn\n c aca prout caca"; - fprintf(stderr2,"Les infos que j'ai récupéré: %s;;\n", ssh_auth_info_ret); if (!ssh_auth_info_ret || !*ssh_auth_info_ret) { - DBG(("No SSH auth info, impossible de traiter")); + D("Impossible de récupérer les données de connection SSH, impossible de traiter"); return PAM_AUTHINFO_UNAVAIL; } copyUntilEndline(ssh_auth_info_ret,ssh_auth_info); - DBG(("Infos de connection: %s",ssh_auth_info)); + DBG("Infos de connection: %s",ssh_auth_info); - const char delim = ' '; - - char * authType = ssh_auth_info; - char * sshKeyType = strtokk(ssh_auth_info, delim); - char * sshKeyVal = strtokk(sshKeyType, delim); - - DBG(("Authentification Type: '%s'", authType)); - DBG(("Authentification KeyType: '%s'", sshKeyType)); - DBG(("Authentification KeyVal: '%s'", sshKeyVal)); + authType = ssh_auth_info; + sshKeyType = strtokk(ssh_auth_info, ' '); + sshKeyVal = strtokk(sshKeyType, ' '); + DBG("Authentification Type: '%s'", authType); + DBG("Authentification KeyType: '%s'", sshKeyType); + DBG("Authentification KeyVal: '%s'", sshKeyVal); rc = oath_init(); if (rc != OATH_OK) { - DBG(("oath_init() failed (%d)", rc)); + DBG("oath_init() failed (%d)", rc); retval = PAM_AUTHINFO_UNAVAIL; goto done; } - - /****** Get oath secret from database ******/ - char connInfo[BDD_CONN_LENGTH] = "dbname='pipi' user=pipisys password='"; - char lastAp = '\''; - FILE *dbPassFile; - char ch; - int pos = strlen(connInfo); + /****** Get oath secret from database ******/ dbPassFile = fopen(BDD_PASS_FILE,"r"); if (dbPassFile == NULL) { - DBG(("Cannot open file %s, on peut pas se connecter à la base de données avec l'UID %s\n", BDD_PASS_FILE, getuid())); + DBG("Cannot open file %s, on peut pas se connecter à la base de données avec l'UID %s\n", BDD_PASS_FILE, getuid()); retval = PAM_AUTHINFO_UNAVAIL; goto done; } @@ -225,14 +215,13 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv fclose(dbPassFile); connInfo[pos] = '\''; - fprintf(stderr2,"On se connecte à la bdd\n"); conn = PQconnectdb(connInfo); /* Vérifier que la connexion au backend a été faite avec succès */ if (PQstatus(conn) != CONNECTION_OK) { - DBG(("Connection to database failed: %s", PQerrorMessage(conn))); + DBG("Connection to database failed: %s", PQerrorMessage(conn)); retval = PAM_AUTH_ERR; goto done; } @@ -240,23 +229,22 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv res = PQexec(conn, "SELECT pg_catalog.set_config('search_path', '', false)"); if (PQresultStatus(res) != PGRES_TUPLES_OK) { - DBG(("SET failed: %s", PQerrorMessage(conn))); + DBG("SET failed: %s", PQerrorMessage(conn)); PQclear(res); retval = PAM_AUTH_ERR; goto done; } - DBG(("Initialisation de la base de données efféctuée\n")); - fprintf(stderr2,"Initialisation de la connection à la bdd effectuée\n"); + DBG("Initialisation de la base de données efféctuée\n"); PQclear(res); - const char *paramValues[2]; + paramValues[0] = sshKeyType; paramValues[1] = sshKeyVal; res = PQexecParams(conn, "SELECT \"userID\",\"oathPrivate\" FROM git.keys WHERE \"sshKeyType\"=$1 AND \"sshPubKey\"=$2",2,NULL,paramValues,NULL,NULL,1); if (PQresultStatus(res) != PGRES_TUPLES_OK) { - DBG(("Impossible de faire la requete à la BDD: %s", PQerrorMessage(conn))); + DBG("Impossible de faire la requete à la BDD: %s", PQerrorMessage(conn)); PQclear(res); retval = PAM_AUTH_ERR; goto done; @@ -264,7 +252,7 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv nFields = PQntuples(res); if(nFields!=1){ - DBG(("Aucun code secret oath trouvé pour la clé '%s'", sshKeyVal)); + DBG("Aucun code secret oath trouvé pour la clé '%s'", sshKeyVal); PQclear(res); retval = PAM_AUTH_ERR; goto done; @@ -273,11 +261,7 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv gitUserID = ntohl(*((int*)PQgetvalue(res, 0, 0))); oathSecret = PQgetvalue(res, 0, 1); - DBG(("On a récupéré le code secret : %s",oathSecret)); - - if(PQgetisnull(res, 0, 0)==1){ - printf("Le champ est bien nul !\n"); - } + DBG("On a récupéré le code secret : %s",oathSecret); PQclear(res); PQfinish(conn); @@ -285,8 +269,6 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv /*** Parsing hex to byte array ***/ - char oathSecretBin[OTP_SECRET_LEN]; - int oathSecretBinLen = OTP_SECRET_LEN+1; oath_hex2bin(oathSecret,oathSecretBin,&oathSecretBinLen); @@ -300,26 +282,8 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv } pmsg[0] = & msg[0]; - { - const char * query_template = "One-time password (OATH) for `%s': "; - size_t len = strlen(query_template) + strlen(user); - size_t wrote; - - query_prompt = malloc(len); - if (!query_prompt) { - retval = PAM_BUF_ERR; - goto done; - } - - wrote = snprintf(query_prompt, len, query_template, user); - if (wrote < 0 || wrote >= len) { - retval = PAM_BUF_ERR; - goto done; - } - - msg[0].msg = query_prompt; - } - + + msg[0].msg = "Votre mot de passe OTP: "; msg[0].msg_style = PAM_PROMPT_ECHO_OFF; resp = NULL; @@ -330,32 +294,32 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv query_prompt = NULL; if (retval != PAM_SUCCESS) { - DBG(("conv returned error: %s", pam_strerror(pamh, retval))); + DBG("conv returned error: %s", pam_strerror(pamh, retval)); goto done; } - DBG(("conv returned: %s", resp -> resp)); + DBG("conv returned: %s", resp -> resp); password = resp -> resp; if (password) password_len = strlen(password); else { - DBG(("Could not read password")); + DBG("Could not read password"); retval = PAM_AUTH_ERR; goto done; } if (password_len < MIN_OTP_LEN) { - DBG(("OTP too short: %s", password)); + DBG("OTP trop court: %s", password); retval = PAM_AUTH_ERR; goto done; } else if (password_len < cfg.digits) { - DBG(("OTP shorter than digits=%d: %s", cfg.digits, password)); + DBG("OTP trop court, on a demandé plus de chiffres: %s", cfg.digits, password); retval = PAM_AUTH_ERR; goto done; } else if (password_len > MAX_OTP_LEN) { - DBG(("OTP too long (and no digits=): %s", password)); + DBG("OTP trop long: %s", password); retval = PAM_AUTH_ERR; goto done; } else { @@ -363,7 +327,7 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv password = NULL; } - DBG(("Pouf ! OTP: %s", otp ? otp : "(null)")); + DBG("Pouf ! OTP: %s", otp ? otp : "(null)"); @@ -371,40 +335,43 @@ pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char ** argv /****** Validation du mot de passe oath ******/ { time_t last_otp; - time_t jetzt = 0; - time(&jetzt); + time_t jetzt; int timeStep = 30; - DBG(("Validating oath secret %s of length %i at time %ld",oathSecret,oathSecretBinLen, jetzt)); - char cdex[32]; + + time(&jetzt); + + DBG("Validation du code secret %s, longueur %i, temps %ld",oathSecret,oathSecretBinLen,jetzt); + rc = oath_totp_validate(oathSecretBin, oathSecretBinLen, jetzt, timeStep, 0, cfg.window, otp); } if (rc == OATH_INVALID_OTP) { - DBG(("One-time password not authorized to login as user '%s'", user)); + DBG("Mot de passe OTP invalide."); retval = PAM_AUTH_ERR; goto done; } - + retval = PAM_SUCCESS; - // On met l'id de l'utisateur pour les autorisations - char envStr[11+8]; + /****** On met l'id de l'utisateur pour les autorisations ******/ sprintf(envStr, "GIT_USERID=%d",gitUserID); pam_putenv(pamh,envStr); /****** Terminé ! ******/ done: - fclose(stderr2); + oath_done(); free(query_prompt); free(onlypasswd); - DBG(("Terminé ! [%s]", pam_strerror(pamh, retval))); + DBG("Terminé ! [%s]", pam_strerror(pamh, retval)); return retval; } + + int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc ,const char **argv) {