1#!/usr/bin/perl -t 2 3# OpenVPN PAM AUTHENTICATON 4# This script can be used to add PAM-based authentication 5# to OpenVPN 2.0. The OpenVPN client must provide 6# a username/password, using the --auth-user-pass directive. 7# The OpenVPN server should specify --auth-user-pass-verify 8# with this script as the argument and the 'via-file' method 9# specified. The server can also optionally specify 10# --client-cert-not-required and/or --username-as-common-name. 11 12# SCRIPT OPERATION 13# Return success or failure status based on whether or not a 14# given username/password authenticates using PAM. 15# Caller should write username/password as two lines in a file 16# which is passed to this script as a command line argument. 17 18# CAVEATS 19# * Requires Authen::PAM module, which may also 20# require the pam-devel package. 21# * May need to be run as root in order to 22# access username/password file. 23 24# NOTES 25# * This script is provided mostly as a demonstration of the 26# --auth-user-pass-verify script capability in OpenVPN. 27# For real world usage, see the auth-pam module in the plugin 28# folder. 29 30use Authen::PAM; 31use POSIX; 32 33# This "conversation function" will pass 34# $password to PAM when it asks for it. 35 36sub my_conv_func { 37 my @res; 38 while ( @_ ) { 39 my $code = shift; 40 my $msg = shift; 41 my $ans = ""; 42 43 $ans = $password if $msg =~ /[Pp]assword/; 44 45 push @res, (PAM_SUCCESS(),$ans); 46 } 47 push @res, PAM_SUCCESS(); 48 return @res; 49} 50 51# Identify service type to PAM 52$service = "login"; 53 54# Get username/password from file 55 56if ($ARG = shift @ARGV) { 57 if (!open (UPFILE, "<$ARG")) { 58 print "Could not open username/password file: $ARG\n"; 59 exit 1; 60 } 61} else { 62 print "No username/password file specified on command line\n"; 63 exit 1; 64} 65 66$username = <UPFILE>; 67$password = <UPFILE>; 68 69if (!$username || !$password) { 70 print "Username/password not found in file: $ARG\n"; 71 exit 1; 72} 73 74chomp $username; 75chomp $password; 76 77close (UPFILE); 78 79# Initialize PAM object 80 81if (!ref($pamh = new Authen::PAM($service, $username, \&my_conv_func))) { 82 print "Authen::PAM init failed\n"; 83 exit 1; 84} 85 86# Authenticate with PAM 87 88$res = $pamh->pam_authenticate; 89 90# Return success or failure 91 92if ($res == PAM_SUCCESS()) { 93 exit 0; 94} else { 95 print "Auth '$username' failed, PAM said: ", $pamh->pam_strerror($res), "\n"; 96 exit 1; 97} 98