Apache-AuthenProgram

 view release on metacpan or  search on metacpan

AuthenProgram.pm  view on Meta::CPAN

# Apache::AuthenProgram allows you to call an external program
# that performs username/password authentication in Apache.
#
# Copyright (c) October 7, 2002 Mark Leighton Fisher, Thomson Inc.
# 
# This module is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.


package Apache::AuthenProgram;

use strict;

AuthenProgram.pm  view on Meta::CPAN

use File::Temp q(tempfile);

$Apache::AuthenProgram::VERSION = '0.90';


sub handler {
    my $request  = shift;	# Apache request object
    my @args     = ();		# authentication program arguments
    my $cmd      = "";		# program command string
    my $i        = 0;		# counter for @args
    my $ofh      = "";		# output file handle for password temp file
    my $password = "";		# password from Basic Authentication
    my $passfile = "";		# temporary file containing password
    my $passtype = "";		# "File" if communicating password by temp file
    my $program  = "";		# authentication program filename
    my $response = ""; 		# Apache response object
    my $success  = "";		# success string from authentication program
    my $username = "";		# username from Basic Authentication

    # get password, decline if not Basic Authentication
    ($response, $password) = $request->get_basic_auth_pw;
    return $response if $response;

    # get username
    $username = $request->connection->user;
    if ($username eq "") {
	$request->note_basic_auth_failure;
        $request->log_reason("Apache::AuthenProgram - No Username Given", $request->uri);
        return AUTH_REQUIRED;
    }

    # get authentication program, args, and success string
    $program = $request->dir_config("AuthenProgram");
    for ($i = 1; $i < 10; $i++) {
        $args[$i] = $request->dir_config("AuthenProgramArg$i");
    }
    $success = $request->dir_config("AuthenProgramSuccess");

    # write temp. password file on request
    $passtype = $request->dir_config("AuthenProgramPassword");
    if ($passtype eq "File") {
        ($ofh, $passfile) = tempfile();
        if (!defined($ofh) || $ofh eq "") {
            $request->log_reason("Apache::AuthenProgram can't create password file",
	     $request->uri);
            return SERVER_ERROR;
        }
        chmod(0600, $passfile)
         || $request->log_reason(
         "Apache::AuthenProgram can't chmod 0600 password file '$passfile' because: $!",
	 $request->uri);
        if (!print $ofh $password,"\n") {
            $request->log_reason("Apache::AuthenProgram can't write password file '$ofh'",
	     $request->uri);
            return SERVER_ERROR;
        }
        if (!close($ofh)) {
            $request->log_reason("Apache::AuthenProgram can't close password file '$ofh'",
	     $request->uri);
            return SERVER_ERROR;
        }
        $password = $passfile;
    }

    # execute command, then examine output for success or failure
    $cmd = "$program '$username' '$password' ";
    $cmd .= join(' ', @args);
    my @output = `$cmd`;
    if ($passtype eq "File") {
        if (!unlink($passfile)) {
            $request->log_reason("Apache::AuthenProgram can't delete password file '$ofh'",
	     $request->uri);
        }
    }
    if (!grep(/$success/, @output)) {
	$request->note_basic_auth_failure;
	$request->log_reason("login failure: " . join(' ', @output), $request->uri);
	return AUTH_REQUIRED;
    }

    unless (@{ $request->get_handlers("PerlAuthzHandler") || []}) {

AuthenProgram.pm  view on Meta::CPAN

    </Directory>

    These directives can be used in a .htaccess file as well.

    If you wish to use your own PerlAuthzHandler then the require 
    directive should follow whatever handler you use.

= head1 DESCRIPTION

This mod_perl module provides a reasonably general mechanism
to perform username/password authentication in Apache by
calling an external program.  Authentication by an external
program is useful when a program can perform an authentication
not supported by any Apache modules (for example, cross-domain
authentication is not supported by Apache::NTLM or
Apache::AuthenSmb, but is supported by Samba's smbclient
program).

You must define the program pathname AuthenProgram and the
standard output success string AuthenProgramSuccess.
The first two arguments to the program are the username and
either the password or a temporary file with the password, 
depending on whether AuthenProgramPassword has the value "File".
"File" forces sending the password to AuthenProgram through a
temporary file to avoid placing passwords on the command line where
they can be seen by ps(1).

Additional program arguments can be passed in the variables
AuthenProgramArg1, AuthenProgramArg2, etc.  Up to 9 of these
variables are supported.

The examples/ subdirectory has sample programs for doing
Samba-based SMB authentication (examples/smblogon),
Oracle authentication (examples/oralogon), and
a simple example (examples/filelogon) that demonstrates communicating
the password through a temporary file.

If you are using this module please let me know, I'm curious how many
people there are that need this type of functionality.

This module was adapted from Apache::AuthenSmb.

=head1 AUTHOR

Mark Leighton Fisher <fisherm@tce.com>

README  view on Meta::CPAN

Apache::AuthenProgram is a mod_perl module that provides a
reasonably general mechanism to perform username/password
authentication in Apache by calling an external program.
Authentication by an external program is useful when a
program can perform an authentication not supported by any
Apache modules (for example, cross-domain authentication is
not supported by Apache::NTLM or Apache::AuthenSmb, but is
supported by Samba's smbclient program).

Installing Apache::AuthenProgram follows the normal CPAN
convention:
    perl Makefile.PL

examples/filelogon  view on Meta::CPAN

#!/www/perl-5.6.1/bin/perl -Tw
# Simple authentication with password sent by file.

# ------ pragmas
use strict;

# ------ define variables
my $passfile = "";		# password file
my $password = "";		# password for $username from $passfile
my $username = "";		# username to authenticate with

# ------ get username and password
if (scalar(@ARGV) < 2) {
    die "usage: file-auth username passwordfile\n";
}
$ARGV[0]  =~ m#([^`']+)#;
$username = $1;
$ARGV[1]  =~ m#([^`']+)#;
$passfile = $1;
open(IFH, $passfile)
 || die "FAILURE: can't open password file '$passfile' because: $!\n";
$password = <IFH>;
chomp($password);
close(IFH)
 || die "FAILURE: can't close password file '$passfile' because: $!\n";
if (!defined($password) || $password =~ m/^\s*$/) {
    die "FAILURE: missing or empty password\n";
}

# ------ verify username/password
if ($username eq "fred" && $password eq "Scooby-Do!2002") {
    print "OK: File login succeeded.\n";
} else {
    print "FAILURE: bad username or password.\n";
}

examples/oralogon  view on Meta::CPAN

# NOTE: Runs in taint mode because it is usually
#       invoked by other programs (mainly CGIs).


# ------ pragmas
use strict;

# ------ define variables
my $database = "";	# Oracle TNS database name
my @output   = ();	# output of SQL*Plus command
my $password = "";	# password for $username
my $sqlplus		# Oracle SQL*Plus interactive query program
 = "/www/oracle/u01/app/oracle/product/7.3.4/bin/sqlplus";
my $username = "";	# Oracle username to authenticate with

# ------ force secure PATH
$ENV{"PATH"} = "/bin:/usr/bin";

# ------ extract username + password + database
if (scalar(@ARGV) < 3) {
    die "usage: oralogon username password TNSname\n";
}
$ARGV[0]  =~ m#([^`']+)#;
$username =  $1;
$ARGV[1]  =~ m#([^`']+)#;
$password =  $1;
$ARGV[2]  =~ m#(([a-zA-Z0-9]|-|\+|_|\.)+)#;
$database =  $1;

# ------ run Oracle SQL*Plus, check that authentication succeeded
@output =<<`endSQLPLUS`;
$sqlplus $username/$password\@$database<<endCMD
$password
quit
endCMD
endSQLPLUS
if (grep(/Connected to:/, @output)) {
    print "OK: Oracle login succeeded.\n";
} else {
    print "FAILURE:\n@output\n";
}

examples/smblogon  view on Meta::CPAN

# NOTE: Runs in taint mode because it is usually
#       invoked by other programs (mainly CGIs).


# ------ pragmas
use strict;


# ------ define variables
my @output   = ();	# smbclient output lines
my $password = "";	# $username's password
my $server   = "";	# server NetBIOS name
my $share    = "";	# share on $server (cannot be hidden share)
my $smbclient		# Samba smbclient pathname
 = "/www/bin/smbclient";
my $username = "";	# user ID for access


# ------ verify and untaint arguments
$ENV{"PATH"} = "/bin:/usr/bin";
if (scalar(@ARGV) < 4) {
    die "usage: smblogon username password server share\n";
}
$ARGV[0] =~ m#([^`']+)#;
$username = $1;
$ARGV[1] =~ m#([^`']+)#;
$password = $1;
$ARGV[2] =~ m#(([a-zA-Z0-9]|-|\+|_|\.)+)#;
$server   = $1;
$ARGV[3] =~ m#(([a-zA-Z0-9]|-|\+|_|\.)+)#;
$share    = $1;


# ------ test ability to logon to local domain
@output = `$smbclient //$server/$share '$password' -U '$username' -c ''`;
if (!grep(/session setup failed/, @output)
 && grep(/Domain=.* OS=.* Server=/, @output)) {
    print "OK: SMB login succeeded.\n";
    exit 0;
} else {
    print "FAILURE:\n@output";
    exit 1;
}



( run in 0.526 second using v1.01-cache-2.11-cpan-49f99fa48dc )