File: //proc/self/root/scripts.20110531.215904.25158/fp-auth
#!/usr/bin/perl
# cpanel - fp-auth Copyright(c) 2010 cPanel, Inc.
# All rights Reserved.
# copyright@cpanel.net http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited
#
#cPanel fp-auth Passthrough Auth Wrapper
#Version 6.0
#
BEGIN { unshift @INC, '/usr/local/cpanel'; }
use Cpanel::FrontpageAdmin ();
use Cpanel::StringFunc ();
use Cpanel::AccessIds ();
use Cpanel::CheckPass ();
use strict;
my $hasmd5 = 0;
eval {
require Digest::MD5;
$hasmd5 = 1;
};
if ( !$hasmd5 ) {
print STDERR "[fp-auth] Digest::MD5 is missing\n";
_internal_error('the Digest::MD5 module being unloadable');
}
my $nobodygid = ( getgrnam("nobody") )[2];
my $httpuid = ( getpwuid("nobody") )[2];
if ( $httpuid eq "" ) {
$httpuid = ( getpwuid("nouser") )[2];
}
if ( $> == 0 ) {
my %MODLIST = (
'SHTML' => '/_vti_bin/shtml.exe',
'FPCOUNT' => '/_vti_bin/fpcount.exe',
'AUTHOR' => '/_vti_bin/_vti_aut/author.exe',
'ADMIN' => '/_vti_bin/_vti_adm/admin.exe',
'ADMINCGI' => '/_vti_bin/_vti_adm/fpadmcgi.exe'
);
my $KEYLEN = 128;
my $FPKEYDIR = '/usr/local/frontpage/version5.0/apache-fp';
my $KEYFILE = '/usr/local/frontpage/version5.0/apache-fp/suidkey.' . getpgrp();
my $FPDIR = '/usr/local/frontpage/version5.0/exes';
my $FPEXE = $ENV{'FPEXE'};
my $FPEXEDIR = $ENV{'FPEXEDIR'};
my $FPFD = $ENV{'FPFD'};
my $FPUID = $ENV{'FPUID'};
my $FPGID = $ENV{'FPGID'};
open( my $keyfile_fh, '<', $KEYFILE );
my $KEY;
{
local ($/);
$KEY = readline($keyfile_fh);
}
close($keyfile_fh);
my $sentkey;
open( my $fpfd_fh, '<&=' . $FPFD );
read( $fpfd_fh, $sentkey, $KEYLEN );
close($fpfd_fh);
if ( $sentkey ne $KEY || $KEY eq '' ) {
print STDERR "[fp-auth] Key mismatch\n";
_internal_error('Key Mismatch');
}
Cpanel::AccessIds::setuids($FPUID);
my $exeok = 0;
foreach my $exe ( keys %MODLIST ) {
if ( $MODLIST{$exe} eq $FPEXE ) {
@ARGV = ( $FPDIR . $MODLIST{$exe} );
$exeok = 1;
}
}
if ( !$exeok ) {
print STDERR "[fp-auth] EXE is $FPEXE\n";
_internal_error($FPEXE);
}
}
if ( $> eq $httpuid ) {
print STDERR "[fp-auth] still runnning as nobody\n";
_internal_error('it was unable to change uids to the requested uid. This is usually because the User/Group line is missing from the VirtualHost entry for this domain in httpd.conf.');
}
_fixuphostenvs();
if ( $ENV{'HTTP_PASSTHROUGH_NEEDED'} eq "" ) {
#auth not needed since passthrough not set
exec @ARGV;
}
$SIG{'ALRM'} = sub {
print "Status: 500\r\n";
print "Connection: close\r\n\r\n";
die();
};
my $Magic = '$1$'; # Magic string
my $itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
my $pass;
if ( $ENV{'HTTP_PASSTHROUGH_PASS'} ) {
$pass = $ENV{'HTTP_PASSTHROUGH_PASS'};
delete $ENV{'HTTP_PASSTHROUGH_PASS'};
}
else {
alarm(30);
open( HP, "<&$ENV{'HTTP_PASSTHROUGH_FD'}" );
$pass = <HP>;
close(HP);
alarm(0);
}
my ($authok) = 0;
my $user = $ENV{'REMOTE_USER'};
my $docroot = $ENV{'DOCUMENT_ROOT'};
my $cpass;
my $myuid = ( getpwuid($>) )[2];
my $homedir = ( getpwuid($>) )[7];
my (%WEBS);
$WEBS{$docroot} = 1;
Cpanel::FrontpageAdmin::loadsubwebs( \%WEBS, $docroot, 1 );
my $web = $ENV{'SCRIPT_NAME'};
$web =~ s/\/_vti_.*$//g;
if ( !-e "${docroot}/${web}/.htaccess" ) { $web = ''; }
my $authfile = "${docroot}/${web}/_vti_pvt/service.pwd";
my $grpfile = "${docroot}/${web}/_vti_pvt/service.grp";
open( HTACCESS, "${docroot}/${web}/.htaccess" );
while (<HTACCESS>) {
if (/^[\s\t]*AuthUserFile (\S+)/) { $authfile = $1; }
if (/^[\s\t]*AuthGroupFile (\S+)/) { $grpfile = $1; }
}
close(HTACCESS);
open( AUTHFILE, "$authfile" ) || do {
print STDERR "[fp-auth] [error] Cannot open $authfile uid=$> gid=$)\n";
_internal_error("Cannot open $authfile uid=$> gid=$)");
};
while (<AUTHFILE>) {
s/\n//g;
if (/^${user}:/) { ( undef, $cpass ) = split( /:/, $_, 2 ); last; }
}
close(AUTHFILE);
open( AUTHFILE, "$grpfile" ) || do {
print STDERR "[fp-auth] [error] Cannot open $grpfile uid=$> gid=$)\n";
_internal_error("Cannot open $grpfile uid=$> gid=$)");
};
while (<AUTHFILE>) {
s/\n//g;
s/^[\s\t]*//g;
my ( $group, $users ) = split( /:/, $_ );
my @USERS = split( / /, $users );
foreach my $testuser (@USERS) {
$testuser =~ s/[\s\t]*//g;
if ( $user eq $testuser ) {
$ENV{'REMOTE_GROUP'} = $group;
last;
}
}
if ( $ENV{'REMOTE_GROUP'} ne "" ) { last; }
}
close(AUTHFILE);
if ( $cpass ne "" ) {
if ( $cpass =~ /^\$1\$(.+)\$.*/ ) {
if ( Cpanel::CheckPass::unix_md5_crypt( $pass, Cpanel::CheckPass::getsalt($cpass) ) eq $cpass ) {
$authok = 1;
}
}
else {
if ( crypt( $pass, $cpass ) eq $cpass ) {
$authok = 1;
}
}
}
foreach my $docroot ( keys %WEBS ) {
Cpanel::FrontpageAdmin::dopassmod( $docroot, $myuid, $nobodygid );
}
if ( !$authok ) {
my $res = "Status: 401\r\n";
my $err = "Access denied";
if ( $ENV{'HTTP_HOST'} ne "" ) {
$res .= "WWW-Authenticate: Basic realm=\"Secured Frontpage on $ENV{'HTTP_HOST'}\"\r\n";
}
else {
$res .= "WWW-Authenticate: Basic realm=\"Secured Frontpage\"\r\n";
}
$res .= "Connection: close\r\n";
$res .= "Content-length: " . length($err) . "\n";
$res .= "Content-type: text/plain\r\n\r\n";
$res .= $err;
print $res;
if ( $ENV{'REMOTE_USER'} ne "" ) {
print STDERR "[fp-auth] [error] authenticate failed using $authfile user=$ENV{'REMOTE_USER'}. uid=$>\n";
}
local $SIG{'ALRM'} = sub { local $SIG{__DIE__}; die; };
alarm(10);
while (<STDIN>) {
#read stdin to prevent a broken pipe
}
exit();
}
my ($childpid);
if ( !( $childpid = fork() ) ) {
exec @ARGV;
#not reached
exit();
}
else {
$0 = 'fp-auth cleanup';
waitpid( -1, 0 );
my (%NEWWEBS);
Cpanel::FrontpageAdmin::loadsubwebs( \%NEWWEBS, $docroot, 1 );
foreach my $docroot ( keys %NEWWEBS ) {
next if ( $WEBS{$docroot} );
Cpanel::FrontpageAdmin::dopassmod( $docroot, $myuid, $nobodygid );
}
}
exit();
sub _internal_error {
my $error = shift;
my $err = "<HTML><HEAD>\n<TITLE>500 Internal Server Error</TITLE>\n";
$err .= "</HEAD><BODY>\n";
$err .= "<H1>Internal Server Error</H1>\n";
$err .= "The server is temporarily unable to service your\n";
$err .= "request due to $error.\n";
$err .= "</BODY></HTML>\n";
my $send .= "Status: 500\r\n";
$send .= "Connection: close\r\n";
$send .= "Content-length: " . length($err) . "\r\n";
$send .= "Content-type: application/x-vermeer-rpc\r\n\r\n";
$send .= $err;
print $send;
alarm(10);
local $SIG{'ALRM'} = sub { local $SIG{__DIE__}; die; };
while (<STDIN>) {
#read stdin to prevent a broken pipe
}
exit(0);
}
sub _fixuphostenvs {
my $server_port = int $ENV{'SERVER_PORT'} || 80;
my $server_host = $ENV{'SERVER_NAME'};
if ( !-e '/usr/local/frontpage/' . $server_host . ':' . $server_port . '.cnf' ) {
if ( $server_host =~ /^www\./ ) {
$server_host =~ s/^www\.//g;
}
else {
$server_host = 'www.' . $server_host;
}
if ( -e '/usr/local/frontpage/' . $server_host . ':' . $server_port . '.cnf' ) {
$ENV{'SERVER_NAME'} = $server_host;
}
}
}