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
> 

Reply via email to