1=head1 NAME 2 3Authen::PAM::FAQ - Frequently-Asked Questions about Authen::PAM. 4 5=head1 SYNOPSIS 6 7perldoc Authen::PAM::FAQ 8 9=head1 VERSION 10 11This document is currently at version I<0.05>, as of I<May 4, 2005> 12 13=head1 DESCRIPTION 14 15=head2 1. Can I authenticate a user non interactively? 16 17Yes, you can although not in a very clean way. The PAM library 18has a mechanism, in a form of a conversation function, to send and 19receive text data from the user. For details of the format of the 20conversation function consult the Authen::PAM manual. This function 21receives a list of code/string pairs. There are two codes 22(PAM_TEXT_INFO and PAM_ERROR_MSG) for displaying the associated string 23to the user and two codes (PAM_ECHO_ON and PAM_ECHO_OFF) for getting 24input from the user. As you can see the codes are rather general and 25you can not be completely sure when you are asked for a user name and 26when for a password. However, the common practice is that PAM_ECHO_ON 27is used for a user name and PAM_ECHO_OFF is used for a password. So, 28what you can do is to write your own conversation function which 29ignores the PAM_TEXT_INFO and PAM_ERROR_MSG codes and returns the 30user name for the code PAM_ECHO_ON and the password for the code 31PAM_ECHO_OFF. If you pass the user name in the initialization function 32then usually you will not be asked for it. Here is a simple example 33how to do this: 34 35 use Authen::PAM; 36 use POSIX qw(ttyname); 37 38 $service = "login"; 39 $username = "foo"; 40 $password = "bar"; 41 $tty_name = ttyname(fileno(STDIN)); 42 43 sub my_conv_func { 44 my @res; 45 while ( @_ ) { 46 my $code = shift; 47 my $msg = shift; 48 my $ans = ""; 49 50 $ans = $username if ($code == PAM_PROMPT_ECHO_ON() ); 51 $ans = $password if ($code == PAM_PROMPT_ECHO_OFF() ); 52 53 push @res, (PAM_SUCCESS(),$ans); 54 } 55 push @res, PAM_SUCCESS(); 56 return @res; 57 } 58 59 ref($pamh = new Authen::PAM($service, $username, \&my_conv_func)) || 60 die "Error code $pamh during PAM init!"; 61 62 $res = $pamh->pam_set_item(PAM_TTY(), $tty_name); 63 $res = $pamh->pam_authenticate; 64 print $pamh->pam_strerror($res),"\n" unless $res == PAM_SUCCESS(); 65 66 67The Authen::PAM module comes with a default conversation function 68which you can find in the file F<PAM.pm>. 69 70=head2 2. Can I change a password non interactively? 71 72All the discussion of the previous question also applies here. There 73is however one serious complication. When changing a password it is 74quite possible that the PAM library will send you at lest two 75PAM_ECHO_OFF prompts - one for the old password and one or two for the 76new one. Therefore, the first thing you should do is to see what 77sequence of prompts is produced by your service. Then the conversation 78function should include some state variable to distinguish the 79different prompts. Here is an example: 80 81 82 use Authen::PAM; 83 84 $service = "passwd"; 85 $username = "foo"; 86 $oldpassword = "old_pass"; 87 $newpassword = "new_pass"; 88 89 sub my_conv_func { 90 my @res; 91 while ( @_ ) { 92 my $code = shift; 93 my $msg = shift; 94 my $ans = ""; 95 96 $ans = $username if ($code == PAM_PROMPT_ECHO_ON() ); 97 if ($code == PAM_PROMPT_ECHO_OFF() ) { 98 $ans = $oldpassword if ($state == 0); 99 $ans = $newpassword if ($state == 1); 100 $ans = $newpassword if ($state == 2); 101 102 $state++; 103 } 104 105 push @res, (PAM_SUCCESS(),$ans); 106 } 107 push @res, PAM_SUCCESS(); 108 return @res; 109 } 110 111 ref($pamh = new Authen::PAM($service, $username, \&my_conv_func)) || 112 die "Error code $pamh during PAM init!"; 113 114 $state = 0; 115 $res = $pamh->pam_chauthtok; 116 print $pamh->pam_strerror($res),"\n" unless $res == PAM_SUCCESS(); 117 118If you are running the script as root then most likely you will not be 119prompted for an old password. In this case you can simply return the 120new password at the ECHO_OFF prompt. 121 122The $msg variable contains the text of the input prompt which you can 123use for additional test or for debugging purposes, e.g. 124 125 if ($code == PAM_PROMPT_ECHO_OFF() ) { 126 if ($state>=1 || $msg=~/new/i) { # are we asked for a new password 127 $ans = $newpassword; 128 } else { 129 $ans = $oldpassword; 130 } 131 $state++; 132 } 133 134 135=head2 3. Why are the constants PAM_AUTHTOK and PAM_OLDAUTHTOK not avaliable? 136 137The PAM_AUTHTOK and PAM_OLDAUTHTOK items can be used to pass 138authentication tokens (passwords) from one module to another. However, 139they are avaliable only to PAM modules and not to PAM applicatinos. If 140you have a special setup in which you really need to preset the 141password from the application (e.g. using a radius server) then you 142can use the pam_set_authtok module avaliable from 143L<http://www.uni-hohenheim.de/~schaefer/linux/pam/pam_set_authtok.html>. 144 145 146=head1 SEE ALSO 147 148L<Authen::PAM> 149 150=head1 AUTHOR 151 152Nikolay Pelov <NIKIP at cpan.org> 153 154=head1 COPYRIGHT 155 156Copyright (c) 1998-2005 Nikolay Pelov. All rights reserved. This file 157is part of the Authen::PAM library. This library is free software; you 158can redistribute it and/or modify it under the same terms as Perl 159itself. 160 161=cut 162 163