Nétoyage de toutes les sources et suppression de la poudre au yeux de pam_oath_key

This commit is contained in:
Mysaa Java 2021-05-14 20:33:54 +02:00
parent e5c4e6bf13
commit 7eb49b267b
3 changed files with 107 additions and 162 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -11,25 +11,22 @@
#include <arpa/inet.h> //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 <syslog.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <security/pam_modutil.h>
#include <security/pam_ext.h>
// 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)
{