Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

We have a PHP application that is encrypted with IonCube. This application calls an XML file stored in the same directory to get its configuration options.

The license for the software allows us to use it on as many domains as we own, but due to the encryption, we would need to install the script on every single domain we have (we have several thousand). What we want is to point all the domains to the same location on the same server, and just have a single install of the application. When the application tries to read the XML config settings file, we want to serve it a different version of the config information based on the domain the user is browsing from. The config data would be stored in a database we will create.

Since the application is encrypted we cannot make the configuration file a variable or point it to another type of file which could perform some logic and we can't change the way it processes the config file.

Any idea how this could be done within the constraints outlined above?

The only thing I have come up with so far is using a userspace filesystem (maybe based on FUSE) to do it...but I'm hoping there is another way. We are running this on a LAMP platform.

share|improve this question

1 Answer 1

Seems to me your problem breaks down into two areas... the first is a way to get the a program to hand off the configuration info to your web app, and the second is a way to get that program to know something about who is calling it so it can hand off the right config.

The first problem can be solved by using a named pipe. Make the configuration file (say, config.xml) be a named pipe or FIFO, then set up a program that writes to that named pipe.

The second problem is more complicated, since the program that is writing to the named pipe really doesn't know anything about who is on the other end of it. You can solve this with some creative use of lsof. Once you know who is calling you, you can try to find some useful information from their environment to help you know which site is actually being hit.

Here's some pretty crufty perl that tries to solve both problems. You'll no doubt want to tweak this to fit your environment, but hopefully it helps a bit.

#! /usr/bin/perl

use strict;
use POSIX qw(mkfifo);

my $f = "the_config.txt";
unlink $f if -e $f;
mkfifo($f, 0644) or die "mkfifo $f failed: $!\n";

while (1) {
    my ($interesting_command, $interesting_pid);

    unless (-p $f) {
        unlink $f;
        mkfifo($f, 0700) or die "mkfifo $f failed: $!\n";
    }

    # the open blocks until someone else tries to read the pipe
    open(FIFO, "> $f") or die "can't write $f: $!\n";

    # figure out who is on the other end?
    open(LSOF, "lsof $f |") or die "can't run lsof: $!\n";
    while (<LSOF>) {
        chomp;
        my ($command, $pid, $user, $fd) = split(m/\s+/, $_);
        next unless $fd =~ m/\d+r$/; # we are only interested in the reader
        $interesting_command = $command;
        $interesting_pid = $pid;
    }
    close LSOF;

    if (!defined($interesting_pid)) {
        print "couldn't find the corresponding pid, :-(\n";
        close FIFO;
        sleep 2;
        next;
    }

    print FIFO "I see you process $interesting_pid ($interesting_command)\n"
        or die "couldn't print to $f: $!\n";

    my $the_site = get_site($interesting_pid);
    print FIFO "looks like your server name was $the_site\n"
        or die "couldn't print to $f: $!\n";

    close FIFO or die "couldn't close $f: $!\n";
    sleep 2;
    print "looping\n";
}

sub get_site {
    my $pid = shift;
    my $server_name;

    # extract data from his environment...
    local($/) = "\0";
    open(PE, "/proc/$pid/environ") or die "can't open environ for pid $pid\n";
    while (<PE>) {
        my ($key, $val) = split(m/=/, $_);
        next unless $key eq 'SERVER_NAME';
        $server_name = $val;
    }
    close(PE);

    if ($server_name eq '') {
        return "not found, :-(\n";
    }
    return $server_name;
}

I tested this by setting up a simple CGI script to read the file:

#! /usr/bin/perl

print "Content-type: text/html\n\n";

print "<html><head></head><body><pre>\n";
open(F, "/full_path_to_the_named_pipe/the_config.txt");
while (<F>) {
        print;
}
close(F);
print "</pre></body></html>\n";

Hitting this from my personal site prints the domain name that was used to hit it.

Obviously, you'll have to make sure that the user the script is running as has permission to do the lsof and to read the environment of the web server or it won't be able to extract the server name. You'll also need to make sure the script that is writing to the named pipe is always running or your php app will block forever. There are probably a bunch of other caveats, too, but hopefully this is enough to get you started.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.