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