0

Introduction: Our company uses dynamically generated vhosts via mod_perl to generate vhosts from our database. We basically have a table "domains" which is dynamically modified for our hundreds of customers and partners.

We have several kinds of templates with different Aliases, includes and rules. So we basically use the following Perl script to generate different templates:

<Perl>
    #!perl

    use DBI;
    use Time::HiRes qw(time);

    use Apache2::ServerUtil ();
    my $s = Apache2::ServerUtil->server;

    $Apache2::PerlSections::Save = 1;

    my $dsn  = "dbi:mysql:...:...";
    my $user = "...";
    my $pw   = "...";
    my $db   = DBI->connect($dsn, $user, $pw) or die $DBI::errstr;

    my $select = qq/SELECT * FROM domains ORDER BY ID/;
    my $sth_select = $db->prepare($select);

    $sth_select->execute() or die $DBI::errstr;
    my @row;
    while( @row = $sth_select->fetchrow_array ) {
        $My::domain = @row[1];
        $My::dir = @row[3];
        $My::template = @row[4];
        $s->add_config(["Include /srv/www/vhosts/templates/".$My::template]);
    }
</Perl>

In the templates we define the hostname by the variables used in the perl loop.

For preview-purpose we want to protect some of the projects / domains with a database-controlled login. That is where mod_atuhn_dbd comes into the game.


This is our final solution for database-login for different projects and where the actual problem starts:

<VirtualHost *:80>
    DBDriver   mysql
    DBDParams  "host=... dbname=... port=3306 user=... pass=..."
    DBDMin     1
    DBDKeep    2
    DBDMax     10
    DBDExptime 60

    <Perl>
        use File::Copy;
        $ServerName = $My::domain;
        $DocumentRoot = "/srv/www/".$My::dir;

        $Directory {"/srv/www/".$My::dir} = {
            AllowOverride        => "All",
            Order                => "allow,deny",
            deny                 => "from all",
            Satisfy              => "Any",
            Require              => "valid-user",
            AuthType             => "Basic",
            AuthName             => "Achtung",              
            AuthBasicProvider    => "socache dbd",              
            AuthnCacheProvideFor => "dbd",              
            AuthnCacheContext    => "Test",             
            AuthnCacheTimeout    => "60",
            AuthDBDUserPWQuery   => "SELECT `user_passwd` FROM prev_user` WHERE `host_name` = '".$My::dir"' AND `user_name` = %s"               
        };
    </Perl>
</VirtualHost>

problem is - Apache says :

apache2[10988]: $parms->add_config() has failed:
AuthDBDUserPWQuery takes one argument, Query used to fetch password for user at /usr/lib/x86_64-linux-gnu/perl5/5.20/Apache2/PerlSections.pm line 216.\n

If I remove the directive from the perl section and put it into the vhost directly it works as expected and the user will get the prompt and has to log in via the database parameters. Too bad there is no option to use a dynamic host inside the query so this won't really work.

<VirtualHost *:80>
    <Perl>
        [...]
        $Directory {"/srv/www/".$My::dir} = {
            AllowOverride        => "All",
            Order                => "allow,deny",
            deny                 => "from all",
            Satisfy              => "Any",
            Require              => "valid-user",
            AuthType             => "Basic",
            AuthName             => "Achtung",              
            AuthBasicProvider    => "socache dbd",              
            AuthnCacheProvideFor => "dbd",              
            AuthnCacheContext    => "Test",             
            AuthnCacheTimeout    => "60"        
        };
    </Perl>

    <Directory /srv/www/websites/admin> 
        AuthDBDUserPWQuery "SELECT `user_passwd` FROM prev_user` WHERE `host_name` = '[NEED DYNAMIC HOST HERE]' AND `user_name` = %s"
    </Directory>    
</VirtualHost>

There seems to be some odd issue with the following part:

$Directory {"/srv/www/".$My::dir} = {
          [...]
          AuthDBDUserPWQuery   => "SELECT `user_passwd` FROM prev_user` WHERE `host_name` = '".$My::dir"' AND `user_name` = %s"              
};

Any suggestions?

1 Answers1

0

For further information:

Seems to be a bug in mod_perl. Clearing the spaces in the query results in the string being interpreted as one value. Obviously the spaces result in the string being interpreted as multiple values.

So the solution is:

$Directory {"/srv/www/".$My::dir} = {
      [...]
      AuthDBDUserPWQuery   => "SELECT`user_passwd`FROM`prev_user`WHERE`host_name`='".$My::dir"'AND`user_name`=%s"
}

Very dirty and confusing but it works.