#!/usr/bin/perl use strict; use Authen::PAM; &main; sub prompt { my $name = shift; print "$name: "; my $rv = ; chomp($rv); return $rv; } sub main { $| = 1; my $what = prompt "what to do (check or change)"; &check_password_prompted if ( $what eq "check" ); &change_password_prompted if ( $what eq "change" ); } ###################### sub change_password_prompted { my $user = prompt "user"; my $pass = prompt "pass"; my $rv = change_password($user, $pass); print "success\n"; } sub change_password { my $user = shift; my $pass = shift; my $error_msg; my $text_info; my $conv_func = sub { my @res; while ( @_ ) { my $msg_type = shift; my $msg = shift; my $ans; $ans = $user if ( $msg_type == PAM_PROMPT_ECHO_ON ); $ans = $pass if ( $msg_type == PAM_PROMPT_ECHO_OFF ); $error_msg .= "$msg\n" if ( $msg_type == PAM_ERROR_MSG ); $text_info .= "$msg\n" if ( $msg_type == PAM_TEXT_INFO ); push @res, 0; push @res, $ans; } push @res, PAM_SUCCESS; return @res; }; my $pamh = new Authen::PAM("passwd", $user, $conv_func); $pamh->pam_chauthtok == PAM_SUCCESS or die "failed to change auth ($error_msg) ($text_info)"; undef $pamh; warn "error_msg = $error_msg\n" if ( $error_msg ne "" ); warn "text_info = $text_info\n" if ( $error_msg ne "" ); } ###################### sub check_password_prompted { my $user = prompt "user"; my $pass = prompt "pass"; my $service = prompt "service"; my $auth = check_password($user, $pass, $service); print $auth ? "authentication okay\n" : "authentication bad\n"; } sub check_password { my $user = shift; my $pass = shift; my $service_name = shift; my $conv_func = sub { my @res; while ( @_ ) { my $msg_type = shift; my $msg = shift; my $ans; $ans = $user if ( $msg_type == PAM_PROMPT_ECHO_ON ); $ans = $pass if ( $msg_type == PAM_PROMPT_ECHO_OFF ); push @res, 0; push @res, $ans; } push @res, PAM_SUCCESS; return @res; }; my $pamh = Authen::PAM->new($service_name, $user, $conv_func); $pamh->pam_authenticate(PAM_DISALLOW_NULL_AUTHTOK) == PAM_SUCCESS or return 0; $pamh->pam_acct_mgmt(PAM_DISALLOW_NULL_AUTHTOK) == PAM_SUCCESS or return 0; return 1; }