Applied to my tree as 08f8e7af496c22317445f0c34c5eb7dd2caec97c. (I perltidy'd it first)
Matt Simerson wrote: > > New and improved! > With POD! (because JP said so: > http://www.nntp.perl.org/group/perl.qpsmtpd/2005/06/msg3145.html) > Includes usage notes and a perl script useful for diagnosing a checkpassword > program. > > --- > MANIFEST | 1 + > plugins/auth/auth_checkpassword | 127 > +++++++++++++++++++++++++++++++++++++++ > 2 files changed, 128 insertions(+), 0 deletions(-) > create mode 100644 plugins/auth/auth_checkpassword > > diff --git a/MANIFEST b/MANIFEST > index 930ddbf..9d5912a 100644 > --- a/MANIFEST > +++ b/MANIFEST > @@ -62,6 +62,7 @@ plugins/async/queue/smtp-forward > plugins/async/require_resolvable_fromhost > plugins/async/rhsbl > plugins/async/uribl > +plugins/auth/auth_checkpassword > plugins/auth/auth_cvm_unix_local > plugins/auth/auth_flat_file > plugins/auth/auth_ldap_bind > diff --git a/plugins/auth/auth_checkpassword b/plugins/auth/auth_checkpassword > new file mode 100644 > index 0000000..b7ed2ad > --- /dev/null > +++ b/plugins/auth/auth_checkpassword > @@ -0,0 +1,127 @@ > +#!/usr/bin/perl -w > + > +=head1 NAME > + > +auth_checkpassword - Authenticate against a DJB style checkpassword program > + > +=head1 DESCRIPTION > + > +This plugin authenticates users against a DJB style checkpassword program. > Unlike previous checkpassword implementations, this plugin expects qpsmtpd to > be running as the qpsmtpd user. Privilege escalation can be attained by > running the checkpassword binary setuid or with sudo. > + > +=head1 CONFIGURATION > + > +Configure the path to your checkpassword binary: > + > + echo "/usr/local/vpopmail/bin/vchkpw /usr/bin/true" > > ~qpsmtpd/config/smtpauth-checkpassword > + > +vchkpw is the checkpassword program provided by vpopmail. Substitute your > own checkpassword app as appropriate. > + > +If you are using vchkpw and this plugin is being executed by a user ID other > than 89 or 0 (as is the default), and the vchkpw binary is not setuid (as is > the default), this plugin will automatically prepend the vchkpw command with > sudo. If that is the case, you must configure sudo by adding these two lines > to your sudoers file: > + > + Defaults:qpsmtpd closefrom_override > + qpsmtpd ALL = (ALL) NOPASSWD: /usr/local/vpopmail/bin/vchkpw > + > +The closefrom_override option is necessary because, by default, sudo > appropriates the first 3 file descriptors. Those descriptors are necessary to > communicate with the checkpassword program. If you run qpsmtpd as some other > user, adjust the sudo lines approriately. > + > +Using sudo is preferable to enabling setuid on the vchkpw binary. If you > reinstall vpopmail and the setuid bit is lost, this plugin will be broken. > + > +=head1 DIAGNOSTICS > + > +Is the path in the config/smtpauth-checkpassword correct? > + > +Is the path to true in config/smtpauth-checkpassword correct? > + > +Is qpsmtpd running as the qpsmtpd user? If not, did you adjust the sudo > configuration appropriately? > + > +If you are not using sudo, did you remember to make the vchkpw binary setuid > (chmod 4711 ~vpopmail/bin/vchkpw)? > + > +While writing this plugin, I first wrote myself a little test script, which > helped me identify the sudo closefrom_override issue. Here is that script: > + > + #!/usr/bin/perl > + use strict; > + my $sudo = "/usr/local/bin/sudo"; > + $sudo .= " -C4 -u vpopmail"; > + my $vchkpw = "/usr/local/vpopmail/bin/vchkpw"; > + my $true = "/usr/bin/true"; > + > + open(CPW,"|$sudo $vchkpw $true 3<&0"); > + printf(CPW "%s\0%s\0Y123456\0",'u...@example.com','pa55word'); > + close(CPW); > + > + my $status = $?; > + print "FAIL\n" and exit if ( $status != 0 ); > + print "OK\n"; > + > +Save that script to vchkpw.pl and then run it as the same user that qpsmtpd > runs as: > + > + setuidgid qpsmtpd perl vchkpw.pl > + > +If you aren't using sudo, then remove $sudo from the open line. > + > +=head1 ACKNOWLEDGEMENTS > + > +based upon authcheckpassword by Michael Holzt > +and adapted by Johan Almqvist 2006-01-18 > + > +=head1 AUTHOR > + > +Matt Simerson <msimer...@cpan.org> > + > +=head1 COPYRIGHT AND LICENSE > + > +Copyright (c) 2010 Matt Simerson > + > +This plugin is licensed under the same terms as the qpsmtpd package itself. > +Please see the LICENSE file included with qpsmtpd for details. > + > +=cut > + > + > +sub register { > + my ( $self, $qp ) = @_; > + > + $self->register_hook( "auth-plain", "auth_checkpassword" ); > + $self->register_hook( "auth-login", "auth_checkpassword"); > +} > + > +sub auth_checkpassword { > + my ( $self, $transaction, $method, $user, $passClear, $passHash, $ticket > ) = @_; > + > + my $command = $self->qp->config("smtpauth-checkpassword") or return > (DECLINED); > + my ($binary, $params) = $command =~ /^(\S+)(.*)$/; > + > + return(DECLINED) if ( ! -x $binary ); > + my $sudo = get_sudo($binary); > + > + open(CPW,"|$sudo $binary $params 3<&0"); > + printf(CPW "%s\0%s\0Y123456\0",$user,$passClear); > + close(CPW); > + > + my $status = $?; > + > + return(DECLINED) if ( $status != 0 ); > + > + $self->connection->notes('authuser',$user); > + return ( OK, "auth_checkpassword" ); > +} > + > +sub get_sudo { > + my $binary = shift; > + > + return '' if $> == 0; # running as root > + return '' if $> == 89 && $binary =~ /vchkpw/; # running as vpopmail > + > + my $mode = (stat($binary))[2]; > + $mode = sprintf "%lo", $mode & 07777; > + return '' if $mode eq '4711'; # $binary is setuid > + > + my $sudo = `which sudo` || '/usr/local/bin/sudo'; > + return '' if ! -x $sudo; > + $sudo .= ' -C4'; # prevent sudo from clobber file descriptor 3 > + > + return "$sudo -u vpopmail" if $binary =~ /vchkpw/; > + return $sudo; > +} > + > + > + > -- > 1.7.0.6 >