Masquer mot de passe

Résolu/Fermé
aadilove Messages postés 25 Date d'inscription dimanche 30 décembre 2012 Statut Membre Dernière intervention 20 juin 2013 - 11 mars 2013 à 14:49
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 - 14 mars 2013 à 21:23
Bonjour,

Mon but est d'arriver à masquer mon mot de passe lors de la saisie.
pour être plus claire,quand je saisie mon mot de passe sous la console(UNIX) je voudrais avoir des '*' au lieu des caractères tapés.

Merci d'avance...
A voir également:

4 réponses

Utilisateur anonyme
11 mars 2013 à 17:00
yosh !

Je sais pas si quelque chose existe, mais tu peux faire :

a chaque caractère différent de ENTER : je le stock, je clearscreen et j'affiche une '*' en plus
SI le caractère est enter => je valide mes caractères stockés
1
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 841
11 mars 2013 à 20:46
Ta méthode ne marche pas : cela oblige l'utilisateur à appuyer sur la touche entrée pour chaque caractère.
De plus, un écran effacé peut se retrouver sur certains OS en remontant l'ascenseur.
0
Utilisateur anonyme
12 mars 2013 à 08:41
non tu peux simplement faire une boucle (getchar de mémoire mais ca remonte) qui a n'attends que 1 caractère, quelqu'il soit. Toi derriere tu gère ce caractère (enter ou non)
0
Utilisateur anonyme
12 mars 2013 à 08:42
http://membres.multimania.fr/tonysoueid/cour_c/cour_1/chap04.html
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 841
12 mars 2013 à 11:07
Tu oublies une notion basique en C...
Les fonctions de lecture standards (getchar (), ...) ne lisent pas le clavier mais son buffer. Or, pour qu'un caractère entre dans le buffer clavier, il faut appuyer sur la touche entrée.
Le seul moyen est de passer en mode raw () comme dit par Dal.
0
Utilisateur anonyme
12 mars 2013 à 11:37
ah voila je crois que c'est ca : readKey. (ca fait 5/6 ans hein ... et maintenant je taff beaucoup sur windev T_T)
elle te retourne la valeur entière de la touche appuyée (après faut se reporter à l'ascii simplement)
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
11 mars 2013 à 18:49
Salut aadilove,

Sous Linux/Unix, tu dois suspendre l'écho à l'écran des caractères tapés.

Tu peux faire comme indiqué ici :

https://stackoverflow.com/questions/1196418/getting-a-password-in-c-without-using-getpass-3

Si tu tiens absolument à afficher des étoiles (pourquoi ?), c'est plus compliqué, et tu devrais sans doutes utiliser ncurses.

Comme cela :

http://www.cplusplus.com/articles/E6vU7k9E/#CURSES-e2

ncurses est une librairie en C, le code présenté sur ce lien mélange du C avec un style de programmation C++, mais cela devrait te donner une idée et c'est assez simple à corriger. Sinon, tu devrais trouver d'autres exemples programmés de façon plus orthodoxes en C.


Dal
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 841
11 mars 2013 à 20:56
Écrire une * n'est pas beaucoup plus compliqué que passer le terminal en raw.
Avec ton premier lien, tu passes le terminal en raw. Dès que tu lis le caractère entré par l'utilisateur, tu affiches une '*'. Rien de plus.
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié par [Dal] le 12/03/2013 à 11:36
Salut fiddy,

Lorsqu'on permet à l'utilisateur de saisir quelque chose, il est aussi sympa de lui permettre d'effacer sa saisie :-), et donc de gérer la touche backspace, afin qu'elle efface le caractère (l'étoile) précédemment saisie, jusqu'à éventuellement l'étoile représentant la première, et gérer les données de façon correspondante... et gérer aussi la touche entrée, bien sûr.

Donc, si on veut correctement gérer ce type d'interface utilisateur, il faut aller un peu plus loin.

fgets qui est utilisée dans le premier lien ne permet pas de faire cela, car elle ne gère qu'un flux et attend ENTER (ou EOF).

Je pense que getchar pourrait être utilisé, avec le line buffering désactivé (en jouant avec ICANON) en plus de echo, et envoyer \b comme montré dans le 2ème lien pour effacer l'étoile affichée.

Bref, on peut se passer de ncurses, mais ce n'est de toutes façons pas trivial (avec ncurses ou pas, d'ailleurs), de gérer des "étoiles", au lieu de simplement ne rien renvoyer.


Dal
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 841
13 mars 2013 à 20:43
[Dal],
Tu oublies un détail.
Je suis d'accord pour gérer la touche backspace. Mais il faut le faire dans les deux cas (affichage des étoiles ou sans affichage). En effet, en mode raw, chaque backspace provoquera un caractère dans la chaîne de caractère.
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié par [Dal] le 14/03/2013 à 10:26
Non, si seul l'écho est supprimé, le terminal fonctionne sans echo, mais avec le line buffering, et donc la touche backspace est gérée (comme la touche entrée) sans que tu aies à la gérer toi même (comme proposé dans le code sur SO, là https://stackoverflow.com/questions/1196418/getting-a-password-in-c-without-using-getpass-3).

Ce n'est que si tu veux "voir des étoiles", que tu dois supprimer le line buffering, en désactivant en plus le mode canonique, comme proposé dans mon code adapté là : https://forums.commentcamarche.net/forum/affich-27337373-masquer-mot-de-passe#13.


Dal
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié par [Dal] le 12/03/2013 à 12:11
Salut aadilove, fiddy,

Voilà un exemple que j'ai pu tester sur une machine FreeBSD compilé avec gcc, à laquelle je me connecte avec un terminal émulé par Putty, adapté à la fois du premier lien posté dans mon message https://forums.commentcamarche.net/forum/affich-27337373-masquer-mot-de-passe#2 et du 2ème, mais sans utiliser ncurses.

Il devrait fonctionner sous Linux aussi. Voir cependant les remarques ci-après.

#include <stdio.h>    
#include <stdlib.h>    
#include <termios.h>    

#define ENTER_KEY 10    
#define BACKSPACE_KEY 127    

int main(void)    
{    
    struct termios oflags, nflags;    
    char password[11];    
    char ch = ' ';    
    int n = 0;    

    /* disabling line buffering by disabling    
     * canonical mode, in addition to    
     * disabling echo */    
    tcgetattr(fileno(stdin), &oflags);    
    nflags = oflags;    
    nflags.c_lflag &= (~ICANON & ~ECHO);    
    nflags.c_lflag |= ECHONL;    

    if (tcsetattr(fileno(stdin), TCSANOW,    
                &nflags) != 0) {    
        perror("tcsetattr");    
        return EXIT_FAILURE;    
    }    

    printf("password (max len %lu): ",    
            sizeof(password) - 1);    

    do {    
        ch = getchar();    
        if ( (ch != BACKSPACE_KEY) &&    
                (ch != ENTER_KEY) &&    
                (n < sizeof(password) - 1) ) {    
            printf("*");    
            password[n] = ch;    
            password[n+1] = '\0';    
            n++;    
        } else if ( (ch == BACKSPACE_KEY) &&    
                (n > 0) ) {    
            printf("\b \b");    
            n--;    
            password[n] = '\0';    
        }    
    } while (ch != ENTER_KEY);    

    printf("You typed: %s\n", password);    

    /* restore terminal */    
    if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {    
        perror("tcsetattr");    
        return EXIT_FAILURE;    
    }    

    return 0;    
}

La désactivation du line buffering permet de disposer de la touche pressée avec getchar() sans qu'il soit nécessaire de presser la touche entrée.

Le code proposé ci-dessus interdit aussi la saisie au delà de la capacité maximale de la chaîne password, gère backspace pour l'effacement des étoiles et entrée...

Note que le terminal peut être paramétré pour renvoyer autre chose que 127 (Ctrl-?) lorsque backspace est pressé. Ainsi, mon Putty me permet de paramétrer le terminal émulé en renvoyant Ctrl-H à la place.


Dal
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié par [Dal] le 12/03/2013 à 12:21
Mais donc, c'est plus simple de se contenter d'annuler l'écho sur le terminal, pour ne pas avoir à afficher les étoiles et gérer tout ce qui en découle, et se contenter de faire comme décrit dans le premier lien posté :

https://stackoverflow.com/questions/1196418/getting-a-password-in-c-without-using-getpass-3

C'est aussi plus sûr, a priori, car une personne voyant l'écran ne pourra pas compter les étoiles, et en déduire le nombre de caractères composant le mot de passe.


Dal
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 841
13 mars 2013 à 20:46
c'est plus simple de se contenter d'annuler l'écho sur le terminal, pour ne pas avoir à afficher les étoiles et gérer tout ce qui en découle
En mode raw, le backspace affiche un caractère. Donc cela provoquera l'affichage d'une étoile. Mais cela reste cohérent avec l'entrée du caractère dans la chaîne de caractère. Si tu gères le backspace, tu devras le faire pour les deux variantes. Mais j'admets que cela sera un peu plus simple dans la variante sans affichage.

Pour la sûreté, je suis d'accord. Il n'y a pas photo :-).
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié par [Dal] le 14/03/2013 à 11:19
En passant à la struct termios les paramètres appropriés, tu peux contrôler finement le comportement de la console, et définir dans le champ c_lflag que ECHO est retiré, tout en maintenant ICANON.

https://pubs.opengroup.org/onlinepubs/7908799/xsh/tcsetattr.html
https://pubs.opengroup.org/onlinepubs/7908799/xsh/termios.h.html

Cet extrait de man 3 tcflow est plus clair sur la question :

Canonical and noncanonical mode   
The  setting of the ICANON canon flag in c_lflag determines whether the   
terminal is operating in canonical mode (ICANON  set)  or  noncanonical   
mode (ICANON unset).  By default, ICANON set.   

In canonical mode:   

* Input  is  made  available  line by line.  An input line is available   
  when one of the line delimiters is typed (NL, EOL, EOL2;  or  EOF  at   
  the start of line).  Except in the case of EOF, the line delimiter is   
  included in the buffer returned by read(2).   

* Line editing is enabled (ERASE, KILL; and if the IEXTEN flag is  set:   
  WERASE,  REPRINT,  LNEXT).   A  read(2)  returns  at most one line of   
  input; if the read(2) requested fewer bytes than are available in the   
  current line of input, then only as many bytes as requested are read,   
  and the remaining characters will be available for a future read(2).   

In noncanonical mode input is available immediately (without  the  user   
having  to  type  a line-delimiter character), and line editing is disa   
abled.  

Donc, en conservant le "mode canonique", backspace, enter, etc., se comportent normalement, quand bien même l'écho est supprimé, car le terminal continue de traiter des lignes.

Sur la sécurité, c'est plus que de passer par la commande système stty (qui a le même degré de complexité), mais peut faire l'objet de tours de passe passe, comme montré dans ma proof of concept là https://forums.commentcamarche.net/forum/affich-27337373-masquer-mot-de-passe#24


Dal

... qui trouve que la lecture de ce topic commence à devenir compliquée.
0
aadilove Messages postés 25 Date d'inscription dimanche 30 décembre 2012 Statut Membre Dernière intervention 20 juin 2013
13 mars 2013 à 17:57
Merci tout le monde pour vos propositions..Enfin de compte j'ai procédé de la manière suivante (sans afficher des '*') :
printf(" Passe : ");
system("stty -echo"); // aprés cette ligne tout caractère tapé sera caché
fgets(passe, sizeof(passe), stdin);
system("stty echo"); // on revient en mode normal
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 841
13 mars 2013 à 20:49
Bonne idée pour ne pas afficher les étoiles.
En revanche, l'utilisation de system("stty -echo"); est à bannir car cela pose des problèmes de sécurité et ce n'est même pas posix.
Mais si ces limites ne te dérangent pas, tu as encore plus simple avec la fonction getpass() qui fera ce que tu veux directement ;-).
Et pour info, attention avec fgets(), le '\n' sera stocké dans ta chaîne passe s'il y a la place.
0
[Dal] Messages postés 6194 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 11 octobre 2024 1 092
Modifié par [Dal] le 14/03/2013 à 10:18
Oui, comme dit fiddy faire appel à une commande externe n'est pas terrible.

Voilà ton code avec la correction sur la chaîne récupérée par fgets suggérée par fiddy :

$ cat aadilove.c 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(void) 
{ 
    char passe[11]; 
    char *p; 

    printf(" Passe : "); 
    /* aprés cette ligne tout caractère tapé 
     * devrait être caché, sauf si un utilisateur 
     * a substitué la commande stty */ 
    system("stty -echo"); 
    fgets(passe, sizeof(passe), stdin); 
    if ((p = strchr(passe, '\n')) != NULL) 
        *p = '\0'; 
    /* retour en mode normal */ 
    system("stty echo"); 
    printf("\nVous avez tapé %s, mais rien " 
            "ne devais s'afficher à la saisie\n", passe); 

    return 0; 
}


Voilà une exécution "normale" de ce code :

$ gcc -Wall aadilove.c -o aadilove 
$ ./aadilove 
 Passe : 
Vous avez tapé toto, mais rien ne devais s'afficher à la saisie


Et voilà un exemple de ce qu'un utilisateur, même non privilégié, peut faire de ce code (ici, avec le shell sh - Bourne Shell, adapter pour un autre shell la façon dont les variables d'environnement sont manipulées) :

$ whereis stty 
stty: /bin/stty /usr/src/bin/stty 
$ echo $PATH 
/sbin:/bin:/usr/sbin:/usr/bin:/usr/games:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:/home/ccm/bin 
$ pwd 
/usr/home/ccm/temp/testcommandsub 
$ PATH=/usr/home/ccm/temp/testcommandsub:$PATH 
$ export PATH 
$ echo "echo 'coucou'" > stty ; chmod +x stty 
$ ./aadilove 
coucou 
 Passe : toto 
coucou 

Vous avez tapé toto, mais rien ne devais s'afficher à la saisie 

Il faudrait au minimum mettre le chemin complet de stty ("/bin/stty" dans mon cas) dans ta commande system. Ce n'est pas pratique, car, on pourrait imaginer qu'un système la place ailleurs. Ensuite, tu n'es pas à l'abri non plus que cette commande là soit remplacée par une autre qui fait des tours de passe-passe (cela sera plus difficile), ou des vulnérabilités éventuelles de cette commande.


Dal
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 841
14 mars 2013 à 21:23
Exactement la faille de sécurité à laquelle je pensais.

Il faudrait au minimum mettre le chemin complet de stty
Cela ne change rien ^^. Juste une 6 caractères à taper en plus (sans compter la touche entrée ^^) pour contourner l'appel à /bin/stty. Et on peut recommencer à jouer avec le PATH. Quoi que il me semble que cette ruse soit corrigée sur les noyaux supérieurs à 2.4. Il vaut mieux utiliser la famille exec().
Ou encore mieux, ton programme plus haut :-)
0