Il seguente codice implementa un semplice modulo di autenticazione che effettua due controlli :
si assicura che l’utente sia elencato nel file delle password |
|
richiede una password all’utente e verifica che la sua lunghezza sia almeno di otto caratteri, concedendo in caso positivo l’accesso |
Come richiesto dalle convenzioni della libreria PAM, il modulo definisce le due funzioni pam_sm_authenticate(), che esegue i due compiti elencati sopra, e pam_sm_setcred(), che non esegue nessuna azione. L’esempio illustra l’uso del meccanismo di conversazione, utilizzato per richiedere all’utente la password da verificare.
#include <string.h>
#include <security/pam_appl.h>
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags,
int ritorno;
ritorno=pam_get_user(pamh,&utente,"Inserire nome utente: ");
}
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags,
int argc, const char **argv)
return PAM_SUCCESS;
}
#include <stdio.h>
#include <pwd.h>
#define PAM_SM_AUTH
#include <security/pam_misc.h>
int argc, const char **argv)
{
const char *utente;
const struct pam_conv *conv;
struct passwd *pw; struct pam_message messaggio[1];
const struct pam_message *mes[1];
struct pam_response *risposta;
pw=getpwnam(utente);
if (!pw)
return(PAM_USER_UNKNOWN);
ritorno=pam_get_item(pamh,PAM_CONV,(const void **) &conv);
mes[0]=messaggio;
messaggio[0].msg_style=PAM_PROMPT_ECHO_OFF;
messaggio[0].msg="Inserire la password\n";
conv->conv(1,(const struct pam_message **) mes,&risposta,NULL);
if(strlen(risposta->resp)<8) return PAM_AUTH_ERR;
else return PAM_SUCCESS;
{
Il seguente codice implementa un'applicazione che utilizza PAM e mostra l’estrema versatilità permessa da questa libreria. Essa richiede di autenticare un utente, il cui user-name può essere inserito dalla linea di comando, delegando la scelta del meccanismo di autenticazione all’amministratore di sistema ( che configura il file nella directory /etc/pam.d ). L’applicazione resta all’oscuro di come l’utente viene autenticato, ma , a seconda del valore di ritorno della funzione pam_authenticate(), può decidere di concedere l’accesso all’utente o meno.
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <stdio.h>
static struct pam_conv conv = {
misc_conv,
NULL
};
int main(int argc, char *argv[])
{
pam_handle_t *pamh=NULL;
int ritorno;
const char *utente=NULL;
if(argc == 2)
utente = argv[1];
if(argc > 2) {
printf("Numero argomenti errati. Uso: ver_utente [nome utente]\n");
exit(1);
}ritorno= pam_start("ver_utente",utente, &conv, &pamh);
if (ritorno == PAM_SUCCESS) /* Richiesta alla libreriadi autenticazione*/
ritorno = pam_authenticate(pamh, 0); /* dell'utente tramite il modulo definito in */
else printf("%s \n ",pam_strerror(pamh, ritorno)); /* /etc/pam.d/ver_utente */
if(ritorno==PAM_USER_UNKNOWN)
printf("Utente inesistente \n ");if (ritorno == PAM_SUCCESS)
printf("L'utente è stato autenticato \n");
else
printf("L'utente non è stato autenticato \n");
if (pam_end(pamh,ritorno) != PAM_SUCCESS) {
pamh = NULL;
printf("%s \n ",pam_strerror(pamh, ritorno));
exit(1);
}
}
Quest'ultima sezione dell'appendice illustra una semplice applicazione login che utilizza le API PAM. Ciò non vuol dire che la porzione di codice seguente sia un programma login pienamente funzionante poiché alcune delle funzionalità necessarie non sono state incluse in maniera da enfatizzare l'utilizzo delle API PAM.
// Dichiarazione dei prototipi di funzione
static int login_conv(int num_msg, struct pam_message **msg,
struct pam_response **response, void *appdata_ptr);
struct pam_conv pam_conv = { login_conv, NULL };
pam_handle_t *pamh;
/* handle di autenticazione*/
// Funzione main
void main(int argc, char *argv[], char **renvp) {
/* * Msnca il codice per collezionare i parametri PAM */
/* * Invocare pam_start per dare inizio alle operazioni di autenticazione PAM */if ((pam_start("login", user_name, &pam_conv, &pamh)) != PAM_SUCCESS)
login_exit(1);
pam_set_item(pamh, PAM_TTY, ttyn);
pam_set_item(pamh, PAM_RHOST, remote_host);
while (!authenticated && retry < MAX_RETRIES) {
status = pam_authenticate(pamh, 0);
authenticated = (status == PAM_SUCCESS);
}if (status != PAM_SUCCESS) {
fprintf(stderr, "error: %s\n", pam_strerror(pamh, status));
login_exit(1);
}/* ora controlliamo se l'utente autenticato ha il permesso di effettuare la login. */
if ((status = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS) {
if (status == PAM_AUTHTOK_EXPIRED) {
status = pam_chauthtok(pamh, 0);
if (status != PAM_SUCCESS)
login_exit(1);
}
}/* invoca call pam_open_session per aprire la sessione autenticata
* pam_close_session deve essere invocata dal processo chr
* cancella l'entrata utmp (i.e., init) */if (status = pam_open_session(pamh, 0) != PAM_SUCCESS)
login_exit(status);/* stabilisce le credenziali del processo */
setgid(pwd->pw_gid);
/* * Inizializza la lista supplementare di accesso per i gruppi
* Ciò dovrebbe essere fatto prima di invocare pam_setcred perchè
* il modulo PAM potrebbe aggiungere gruppi durante
* la chiamata a pam_setcred
*/initgroups(user_name, pwd->pw_gid);
status = pam_setcred(pamh, PAM_ESTABLISH_CRED);
if (status != PAM_SUCCESS)
login_exit(status);/* imposta il real (e l'effective) UID */
setuid(pwd->pw_uid);
pam_end(pamh, PAM_SUCCESS);/* Una volta terminato l'utilizzo di PAM
* è possibile implementare le funzionalità
* di login che devono svolgere altri compiti
*/
}
/* login_exit - Effettua una chiamata a exit() e termina.
* Questa funzione viene inserita affinchè PAM possa liberare la memoria
* prima che il processo restituisca il controllo.
*/
static void login_exit(int exit_code) {
if (pamh) pam_end(pamh, PAM_ABORT);
exit(exit_code);
}
/* Corpo della funzione login_conv():
* Questa è la funzione di conv (conversazione) chiamata da
* un modulo di autenticazione PAM per stampare i messaggi di errore
* o per ottenere le informazioni dall'utente.
*/
int login_conv(int num_msg, struct pam_message **msg,
struct pam_response **response, void *appdata_ptr) {
while (num_msg--) {
switch (m->msg_style) {
case PAM_PROMPT_ECHO_OFF:
r->resp = strdup(getpass(m->msg));
break;
case PAM_PROMPT_ECHO_ON:
(void) fputs(m->msg, stdout);
r->resp = malloc(PAM_MAX_RESP_SIZE);
fgets(r->resp, PAM_MAX_RESP_SIZE, stdin);
/* aggiungere codice qui per rimuovere il carattere \n dalla stringa ritornata
da fputs */
break;
case PAM_ERROR_MSG:
(void) fputs(m->msg, stderr);
break;
case PAM_TEXT_INFO:
(void) fputs(m->msg, stdout);
break;
default:
log_error();
break;
}
}
return (PAM_SUCCESS);
}