Comment puis-je écrire un test pour la connection au système?

J'ai écrit un script CGI Python qui invoque les commands bash , et il doit tester pour une connection réussie sur l'hôte.

Comment puis-je écrire un test pour cela?

Par exemple, pourrais-je créer un script bash qui teste une combinaison nom d'user et mot de passe donnée contre l'user enregistré sur l'hôte?

L'utilisation de PAM est la meilleure solution. Vous pouvez écrire un petit code C ou installer le package python-pam et utiliser un script python fourni avec le package python-pam. Voir /usr/share/doc/python-pam/examples/pamtest.py

La bonne approche pour tester si un user peut se connecter est de se connecter réellement en tant qu'user.

Donc, ce que je recommand est de faire utiliser le script CGI pour exécuter su , passer un mot de passe et exécuter la command qui doit être exécutée. Voici un brouillon d'un script attendu qui ne fait que cela (avertissement: absolument non testé, et je ne m'y attend pas). Substituez dans le nom d'user, mot de passe et command (où j'ai écrit bob , swordfish et somecommand ); assurez-vous de citer correctement.

 spawn "/bin/su" "bob" expect "Password:" send "swordfish\r" expect "^\\$" send "somecommand" expect -re "^\\$" send "exit\r" expect eof 

Si vous ne voulez vraiment pas exécuter la command à travers une couche de su (par exemple parce que ce que vous faites doit être exécuté par le process CGI lui-même), utilisez expect pour exécuter la command true et vérifiez que le statut de return est 0 .

Une autre approche serait d'utiliser PAM directement dans votre application, via la binding PAM de Python .

Pour répondre plus spécifiquement: "Est-il possible de créer un script bash qui testera une combinaison de nom d'user et mot de passe donnée contre l'user inscrit sur l'hôte?"

Oui.

 #!/bin/bash uid=`id -u` if [ $uid -ne 0 ]; then echo "You must be root to run this" exit 1 fi if [ $# -lt 1 ]; then echo "You must supply a username to check - ($# supplied)" exit 1 fi username=$1 salt=`grep $username /etc/shadow | awk -F: ' {print substr($2,4,8)}'` if [ "$salt" != "" ]; then newpass=`openssl passwd -1 -salt $salt` grep $username /etc/shadow | grep -q $newpass && echo "Success" || echo "Failure" fi 

Il y a une solution PAM "C", "Python" citée ici, permettez-moi de mettre le perl aussi 🙂

Source: http://search.cpan.org/~nikip/Authen-PAM-0.16/PAM/FAQ.pod#1._Can_I_authenticate_a_user_non_interactively ?

 #!/usr/bin/perl use Authen::PAM; use POSIX qw(ttyname); $service = "login"; $username = "foo"; $password = "bar"; $tty_name = ttyname(fileno(STDIN)); sub my_conv_func { my @res; while ( @_ ) { my $code = shift; my $msg = shift; my $ans = ""; $ans = $username if ($code == PAM_PROMPT_ECHO_ON() ); $ans = $password if ($code == PAM_PROMPT_ECHO_OFF() ); push @res, (PAM_SUCCESS(),$ans); } push @res, PAM_SUCCESS(); return @res; } ref($pamh = new Authen::PAM($service, $username, \&my_conv_func)) || die "Error code $pamh during PAM init!"; $res = $pamh->pam_set_item(PAM_TTY(), $tty_name); $res = $pamh->pam_authenticate; print $pamh->pam_strerror($res),"\n" unless $res == PAM_SUCCESS(); 

Si vous avez un access root, que vous utilisez des passwords md5 et que vous n'avez qu'à comparer les passwords, vous pouvez utiliser le module perl Crypt :: PasswdMD5 . Prenez le MD5 Hash depuis / etc / shadow, supprimez le $ 1 $, puis splitter le rest de $. Champ 1 = Sel, Champ 2 = text crypté. Puis hachez le text entré dans votre CGI, comparez cela au text crypté, et Bob votre oncle.

 #!/usr/bin/env perl use Crypt::PasswdMD5; my $user = $ARGV[0]; my $plain = $ARGV[1]; my $check = qx{ grep $user /etc/shadow | cut -d: -f2 }; chomp($check); my($salt,$md5txt) = $check =~ m/\$1\$([^\$].+)\$(.*)$/; my $pass = unix_md5_crypt($plain, $salt); if ( "$check" eq "$pass" ) { print "OK","\n"; } else { print "ERR","\n"; } 

Après quelques searchs j'ai écrit ce programme C qui peut être utilisé à partir du script

 #include <stdlib.h> #include <stdio.h> #include <pwd.h> #include <shadow.h> #include <ssortingng.h> #include <crypt.h> #include <unistd.h> #include <libgen.h> int main(int argc, char **argv) { struct spwd *pwd; if (argc != 3) { printf("usage:\n\t%s [username] [password]\n", basename(argv[0])); return 1; } else if (getuid() == 0) { pwd = getspnam(argv[1]); return strcmp(crypt(argv[2], pwd->sp_pwdp), pwd->sp_pwdp); } else { printf("You need to be root\n"); return 1; } } 

Vous le comstackz avec:

 gcc -Wall password_check.c /usr/lib/libcrypt.a -o check_passwd 

Vous pouvez l'utiliser comme

 sudo ./check_passwd <user> <password> && echo "success" || echo "failure" 

Puisque vous avez mentionné que vous utilisez CGI en python, il est probablement approprié de supposer que vous utilisez Apache comme server httpd. Si c'est le cas, laissez le process d'authentification de votre programme à Apache et laissez uniquement les personnes authentifiées exécuter vos scripts / programmes cgi.

Il y a de nombreux modules qui peuvent faire l'authentification pour vous sur Apache, cela dépend vraiment du type de mécanisme d'authentification que vous searchz. La façon dont vous avez cité la question semble être liée à l'authentification du count hôte local basée sur / etc / passwd, les files shadow. Module qui vient à ma search rapide à ce sujet est mod_auth_shadow . L'avantage est que vous autorisez une personne faisant autorité (fonctionnant sur le port de privilèges 80) à authentifier l'user / mot de passe pour vous et vous pouvez countr sur des informations authentifiées de l'user pour exécuter les commands au nom de l'user si nécessaire.

Bons liens pour commencer:

http://adam.shand.net/archives/2008/apache_tips_and_sortingcks/#index5h2

http://mod-auth-shadow.sourceforge.net/

http://www.howtoforge.com/apache_mod_auth_shadow_debian_ubuntu

Une autre approche consiste à utiliser le module SuEXEc d'Apache, qui exécute les process (programmes CGI) au nom de l'user authentifié.

Ce code utilisant PAM a fonctionné pour moi:

 #include <security/pam_appl.h> #include <security/pam_misc.h> #include <stdio.h> #include <ssortingng.h> // Define custom PAM conversation function int custom_converation(int num_msg, const struct pam_message** msg, struct pam_response** resp, void* appdata_ptr) { // Provide password for the PAM conversation response that was passed into appdata_ptr struct pam_response* reply = (struct pam_response* )malloc(sizeof(struct pam_response)); reply[0].resp = (char*)appdata_ptr; reply[0].resp_retcode = 0; *resp = reply; return PAM_SUCCESS; } int main (int argc, char* argv[]) { if (argc > 2) { // Set up a custom PAM conversation passing in authentication password char* password = (char*)malloc(strlen(argv[2]) + 1); strcpy(password, argv[2]); struct pam_conv pamc = { custom_converation, password }; pam_handle_t* pamh; int retval; // Start PAM - just associate with something simple like the "whoami" command if ((retval = pam_start("whoami", argv[1], &pamc, &pamh)) == PAM_SUCCESS) { // Authenticate the user if ((retval = pam_authenticate(pamh, 0)) == PAM_SUCCESS) fprintf(stdout, "OK\n"); else fprintf(stderr, "FAIL: pam_authentication failed.\n"); // All done pam_end(pamh, 0); return retval; } else { fprintf(stderr, "FAIL: pam_start failed.\n"); return retval; } } fprintf(stderr, "FAIL: expected two arguments for user name and password.\n"); return 1; } 

La meilleure chose à faire, si vous avez besoin d'un script pour vous connecter à un hôte, est de configurer une key ssh entre les hôtes.

Lien: http://pkeck.myweb.uga.edu/ssh/

J'ai assez soulevé cela de la page


Tout d'abord, installez OpenSSH sur deux machines UNIX, hâtives et lourdes. Cela fonctionne mieux en utilisant les keys DSA et SSH2 par défaut, autant que je peux dire. Tous les autres HOWTO que j'ai vus semblent traiter des keys RSA et SSH1, et les instructions ne sont pas surprenantes de ne pas fonctionner avec SSH2. Sur chaque type de machine ssh somemachine.example.com, établissez une connection avec votre mot de passe habituel. Cela créera un directory .ssh dans votre directory personnel avec les perms appropriés. Sur votre machine principale où vous voulez que vos keys secrètes vivent (disons hurly), tapez

 ssh-keygen -t dsa 

Cela vous requestra une phrase secrète secrète. S'il s'agit de votre key d'identité principale, assurez-vous d'utiliser une bonne phrase de passe. Si cela fonctionne correctement, vous obtiendrez deux files appelés id_dsa et id_dsa.pub dans votre directory .ssh. Remarque: il est possible d'appuyer simplement sur la touche Entrée lorsque vous êtes invité à entrer une phrase secrète, ce qui fera une key sans phrase de passe. C'est une mauvaise idée pour une key d'identité, alors ne le faites pas! Voir ci-dessous pour les utilisations de keys sans phrases de passe.

 scp ~/.ssh/id_dsa.pub burly:.ssh/authorized_keys2 

Copiez le file id_dsa.pub dans le directory .ssh de l'autre hôte avec le nom authorized_keys2. Maintenant burly est prêt à accepter votre key ssh. Comment lui dire quelles keys utiliser? La command ssh-add le fera. Pour un test, tapez

 ssh-agent sh -c 'ssh-add < /dev/null && bash' 

Cela démarrera l'agent ssh, appenda votre identité par défaut (vous demandant votre mot de passe) et engendrera un shell bash. De ce nouveau shell, vous devriez être en mesure de:

 ssh burly 

Vous devriez pouvoir vous connecter