1 |
stephdl |
1.1 |
From fbbf43ad15c1025d9f1e0a2259371ff1533504cd Mon Sep 17 00:00:00 2001 |
2 |
|
|
From: Matt Simerson <matt@tnpi.net> |
3 |
|
|
Date: Mon, 10 May 2010 19:07:48 -0400 |
4 |
|
|
Subject: added auth_checkpassword plugin |
5 |
|
|
|
6 |
|
|
New and improved! |
7 |
|
|
With POD! (because JP said so: http://www.nntp.perl.org/group/perl.qpsmtpd/2005/06/msg3145.html) |
8 |
|
|
Includes usage notes and a perl script useful for diagnosing a checkpassword program. |
9 |
|
|
|
10 |
|
|
Signed-off-by: Robert <rspier@pobox.com> |
11 |
|
|
--- |
12 |
|
|
MANIFEST | 1 + |
13 |
|
|
plugins/auth/auth_checkpassword | 145 +++++++++++++++++++++++++++++++++++++++ |
14 |
|
|
2 files changed, 146 insertions(+), 0 deletions(-) |
15 |
|
|
create mode 100644 plugins/auth/auth_checkpassword |
16 |
|
|
|
17 |
|
|
diff --git a/MANIFEST b/MANIFEST |
18 |
|
|
index 930ddbf..9d5912a 100644 |
19 |
|
|
--- a/MANIFEST |
20 |
|
|
+++ b/MANIFEST |
21 |
|
|
@@ -62,6 +62,7 @@ plugins/async/queue/smtp-forward |
22 |
|
|
plugins/async/require_resolvable_fromhost |
23 |
|
|
plugins/async/rhsbl |
24 |
|
|
plugins/async/uribl |
25 |
|
|
+plugins/auth/auth_checkpassword |
26 |
|
|
plugins/auth/auth_cvm_unix_local |
27 |
|
|
plugins/auth/auth_flat_file |
28 |
|
|
plugins/auth/auth_ldap_bind |
29 |
|
|
diff --git a/plugins/auth/auth_checkpassword b/plugins/auth/auth_checkpassword |
30 |
|
|
new file mode 100644 |
31 |
|
|
index 0000000..6337ff7 |
32 |
|
|
--- /dev/null |
33 |
|
|
+++ b/plugins/auth/auth_checkpassword |
34 |
|
|
@@ -0,0 +1,145 @@ |
35 |
|
|
+#!/usr/bin/perl -w |
36 |
|
|
+ |
37 |
|
|
+=head1 NAME |
38 |
|
|
+ |
39 |
|
|
+auth_checkpassword - Authenticate against a DJB style checkpassword program |
40 |
|
|
+ |
41 |
|
|
+=head1 DESCRIPTION |
42 |
|
|
+ |
43 |
|
|
+This plugin authenticates users against a DJB style checkpassword |
44 |
|
|
+program. Unlike previous checkpassword implementations, this plugin |
45 |
|
|
+expects qpsmtpd to be running as the qpsmtpd user. Privilege |
46 |
|
|
+escalation can be attained by running the checkpassword binary setuid |
47 |
|
|
+or with sudo. |
48 |
|
|
+ |
49 |
|
|
+=head1 CONFIGURATION |
50 |
|
|
+ |
51 |
|
|
+Configure the path to your checkpassword binary: |
52 |
|
|
+ |
53 |
|
|
+ echo "/usr/local/vpopmail/bin/vchkpw /usr/bin/true" > ~qpsmtpd/config/smtpauth-checkpassword |
54 |
|
|
+ |
55 |
|
|
+vchkpw is the checkpassword program provided by vpopmail. Substitute |
56 |
|
|
+your own checkpassword app as appropriate. |
57 |
|
|
+ |
58 |
|
|
+If you are using vchkpw and this plugin is being executed by a user ID |
59 |
|
|
+other than 89 or 0 (as is the default), and the vchkpw binary is not |
60 |
|
|
+setuid (as is the default), this plugin will automatically prepend the |
61 |
|
|
+vchkpw command with sudo. If that is the case, you must configure sudo |
62 |
|
|
+by adding these two lines to your sudoers file: |
63 |
|
|
+ |
64 |
|
|
+ Defaults:qpsmtpd closefrom_override |
65 |
|
|
+ qpsmtpd ALL = (ALL) NOPASSWD: /usr/local/vpopmail/bin/vchkpw |
66 |
|
|
+ |
67 |
|
|
+The closefrom_override option is necessary because, by default, sudo |
68 |
|
|
+appropriates the first 3 file descriptors. Those descriptors are |
69 |
|
|
+necessary to communicate with the checkpassword program. If you run |
70 |
|
|
+qpsmtpd as some other user, adjust the sudo lines approriately. |
71 |
|
|
+ |
72 |
|
|
+Using sudo is preferable to enabling setuid on the vchkpw binary. If |
73 |
|
|
+you reinstall vpopmail and the setuid bit is lost, this plugin will be |
74 |
|
|
+broken. |
75 |
|
|
+ |
76 |
|
|
+=head1 DIAGNOSTICS |
77 |
|
|
+ |
78 |
|
|
+Is the path in the config/smtpauth-checkpassword correct? |
79 |
|
|
+ |
80 |
|
|
+Is the path to true in config/smtpauth-checkpassword correct? |
81 |
|
|
+ |
82 |
|
|
+Is qpsmtpd running as the qpsmtpd user? If not, did you adjust the |
83 |
|
|
+sudo configuration appropriately? |
84 |
|
|
+ |
85 |
|
|
+If you are not using sudo, did you remember to make the vchkpw binary |
86 |
|
|
+setuid (chmod 4711 ~vpopmail/bin/vchkpw)? |
87 |
|
|
+ |
88 |
|
|
+While writing this plugin, I first wrote myself a little test script, |
89 |
|
|
+which helped me identify the sudo closefrom_override issue. Here is |
90 |
|
|
+that script: |
91 |
|
|
+ |
92 |
|
|
+ #!/usr/bin/perl |
93 |
|
|
+ use strict; |
94 |
|
|
+ my $sudo = "/usr/local/bin/sudo"; |
95 |
|
|
+ $sudo .= " -C4 -u vpopmail"; |
96 |
|
|
+ my $vchkpw = "/usr/local/vpopmail/bin/vchkpw"; |
97 |
|
|
+ my $true = "/usr/bin/true"; |
98 |
|
|
+ |
99 |
|
|
+ open(CPW,"|$sudo $vchkpw $true 3<&0"); |
100 |
|
|
+ printf(CPW "%s\0%s\0Y123456\0",'user@example.com','pa55word'); |
101 |
|
|
+ close(CPW); |
102 |
|
|
+ |
103 |
|
|
+ my $status = $?; |
104 |
|
|
+ print "FAIL\n" and exit if ( $status != 0 ); |
105 |
|
|
+ print "OK\n"; |
106 |
|
|
+ |
107 |
|
|
+Save that script to vchkpw.pl and then run it as the same user that |
108 |
|
|
+qpsmtpd runs as: |
109 |
|
|
+ |
110 |
|
|
+ setuidgid qpsmtpd perl vchkpw.pl |
111 |
|
|
+ |
112 |
|
|
+If you aren't using sudo, then remove $sudo from the open line. |
113 |
|
|
+ |
114 |
|
|
+=head1 ACKNOWLEDGEMENTS |
115 |
|
|
+ |
116 |
|
|
+based upon authcheckpassword by Michael Holzt |
117 |
|
|
+and adapted by Johan Almqvist 2006-01-18 |
118 |
|
|
+ |
119 |
|
|
+=head1 AUTHOR |
120 |
|
|
+ |
121 |
|
|
+Matt Simerson <msimerson@cpan.org> |
122 |
|
|
+ |
123 |
|
|
+=head1 COPYRIGHT AND LICENSE |
124 |
|
|
+ |
125 |
|
|
+Copyright (c) 2010 Matt Simerson |
126 |
|
|
+ |
127 |
|
|
+This plugin is licensed under the same terms as the qpsmtpd package itself. |
128 |
|
|
+Please see the LICENSE file included with qpsmtpd for details. |
129 |
|
|
+ |
130 |
|
|
+=cut |
131 |
|
|
+ |
132 |
|
|
+sub register { |
133 |
|
|
+ my ($self, $qp) = @_; |
134 |
|
|
+ |
135 |
|
|
+ $self->register_hook("auth-plain", "auth_checkpassword"); |
136 |
|
|
+ $self->register_hook("auth-login", "auth_checkpassword"); |
137 |
|
|
+} |
138 |
|
|
+ |
139 |
|
|
+sub auth_checkpassword { |
140 |
|
|
+ my ($self, $transaction, $method, $user, $passClear, $passHash, $ticket) = |
141 |
|
|
+ @_; |
142 |
|
|
+ |
143 |
|
|
+ my $command = $self->qp->config("smtpauth-checkpassword") |
144 |
|
|
+ or return (DECLINED); |
145 |
|
|
+ my ($binary, $params) = $command =~ /^(\S+)(.*)$/; |
146 |
|
|
+ |
147 |
|
|
+ return (DECLINED) if (!-x $binary); |
148 |
|
|
+ my $sudo = get_sudo($binary); |
149 |
|
|
+ |
150 |
|
|
+ open(CPW, "|$sudo $binary $params 3<&0"); |
151 |
|
|
+ printf(CPW "%s\0%s\0Y123456\0", $user, $passClear); |
152 |
|
|
+ close(CPW); |
153 |
|
|
+ |
154 |
|
|
+ my $status = $?; |
155 |
|
|
+ |
156 |
|
|
+ return (DECLINED) if ($status != 0); |
157 |
|
|
+ |
158 |
|
|
+ $self->connection->notes('authuser', $user); |
159 |
|
|
+ return (OK, "auth_checkpassword"); |
160 |
|
|
+} |
161 |
|
|
+ |
162 |
|
|
+sub get_sudo { |
163 |
|
|
+ my $binary = shift; |
164 |
|
|
+ |
165 |
|
|
+ return '' if $> == 0; # running as root |
166 |
|
|
+ return '' if $> == 89 && $binary =~ /vchkpw/; # running as vpopmail |
167 |
|
|
+ |
168 |
|
|
+ my $mode = (stat($binary))[2]; |
169 |
|
|
+ $mode = sprintf "%lo", $mode & 07777; |
170 |
|
|
+ return '' if $mode eq '4711'; # $binary is setuid |
171 |
|
|
+ |
172 |
|
|
+ my $sudo = `which sudo` || '/usr/local/bin/sudo'; |
173 |
|
|
+ return '' if !-x $sudo; |
174 |
|
|
+ $sudo .= ' -C4'; # prevent sudo from clobber file descriptor 3 |
175 |
|
|
+ |
176 |
|
|
+ return "$sudo -u vpopmail" if $binary =~ /vchkpw/; |
177 |
|
|
+ return $sudo; |
178 |
|
|
+} |
179 |
|
|
+ |
180 |
|
|
-- |
181 |
|
|
1.7.2.2 |
182 |
|
|
|