Actuellement, j'ai une application graphique qui a deux niveaux d'accès, opérateur et administrateur. Le login et l'authentification sont tous homebrewed et je voudrais changer l'application pour utiliser PAM à la place. Je ne suis pas sûr de ce que la bonne façon de faire est.Différents niveaux d'accès avec PAM
Corrigez-moi si je me trompe, mais il semble que PAM se résume à un "oui" ou "non" vérifier - oui vous pouvez accéder à ce service, ou non vous ne pouvez pas. Il n'y a aucune disposition pour avoir différents niveaux d'accès en fonction de l'utilisateur qui se connecte. Je dois pouvoir dire qui est un opérateur et qui est un administrateur, et je veux être capable de le faire strictement via PAM si possible.
Donc, ma pensée est que je l'avais mis en place deux services avec deux configurations différentes,/etc/pam.d/pamdemo
pour les opérateurs et /etc/pam.d/pamdemo-admin
pour les administrateurs. Mon application essayera alors de s'authentifier contre pamdemo-admin
d'abord, et si cela échoue alors pamdemo
. Si les deux échouent, l'accès est refusé. Suis-je sur la bonne voie ou suis-je complètement hors des rails?
Voici un exemple de code C que j'ai écrit comme preuve de concept. Lorsque je fais le login, je ne veux pas demander à l'utilisateur deux fois ses identifiants. Je l'ai donc il se souvient du nom d'utilisateur à travers les deux pam_start()
appels, mais je ne peux pas accéder pam_get_item(PAM_AUTHTOK)
du niveau de l'application pour faire la même mise en cache pour le mot de passe. Et c'est en essayant de le faire que j'ai réalisé qu'il pourrait y avoir une façon totalement différente de le faire. Je voudrais que cette application fonctionne quelle que soit la méthode d'authentification, que ce soit le nom d'utilisateur/mot de passe ou les tickets ou empreintes digitales Kerberos, peu importe.
pam_handle_t *try_login(const char *service, int *retval)
{
static char * username = NULL;
struct pam_conv pam_conversation = { conv, NULL };
pam_handle_t * pamh;
*retval = pam_start(service, username, &pam_conversation, &pamh);
if (*retval == PAM_SUCCESS) *retval = pam_authenticate(pamh, 0);
if (*retval == PAM_SUCCESS) *retval = pam_acct_mgmt (pamh, 0);
if (*retval == PAM_SUCCESS) *retval = pam_open_session(pamh, 0);
if (username == NULL) {
if (pam_get_item(pamh, PAM_USER, (const void **) &username) == PAM_SUCCESS) {
username = strdup(username);
}
}
if (*retval != PAM_SUCCESS) {
fprintf(stderr, "%s: %s\n", service, pam_strerror(pamh, *retval));
pam_end(pamh, *retval);
pamh = NULL;
}
return pamh;
}
int main(void)
{
pam_handle_t *pamh = NULL;
int retval;
const char *service, *username;
if (!pamh) pamh = try_login("pamdemo-admin", &retval);
if (!pamh) pamh = try_login("pamdemo", &retval);
if (!pamh) {
fprintf(stderr, "Access denied.\n");
return 1;
}
pam_get_item(pamh, PAM_SERVICE, (const void **) &service);
pam_get_item(pamh, PAM_USER, (const void **) &username);
printf("Logged into %s as %s.\n", service, username);
pam_close_session(pamh, 0);
pam_end (pamh, retval);
return 0;
}
Comme écrit ce programme de démonstration répète le « mot de passe: » invite. Je ne veux pas qu'il demande deux fois!