Friday, January 13, 2012

How to Bind SWFs to a Host?


I'm working on a major Flash project that is going to be the core content of a site.



As most of you well know, almost any site can be entirely copied by copying the cached files and the hierarchy (files and folders structure), and it would run without problems on an Apache server with PHP enabled, if used.



What I would like to know is: How to bind SWF files to run on a specific host?



The SWFs will be encrypted, so outsiders won't have access to the methods used to stop the SWF from running on a different host, question is: what method to use?



I think the solution could be hardcoding the host IP inside the SWF, so if the SWF is looking for 123.123.123.123, only a host with that IP would allow the SWF to run further.



The issue is that AS3 alone can't discover the host IP or could it if it's trying to load a resource file? Anyway, that's why I need your help.



EDIT: Ok, seems someone asked for something similar earlier: Can you secure your swf so it checks if it is running on a recognized environment? I'll try that and see how it works, but the question is still open in case anyone has different suggestions.

4 comments:

  1. One method you could try is a php script that the swf sends a request to and must receive a correct reply from before it continues to operate. Since people can't get at your server-side php, they can't get the needed code to simulate that reply.

    ReplyDelete
  2. The SWFs will be encrypted, so outsiders won't have access to the methods used to stop the SWF from running on a different host
    Since the file will run on a client computer (and thus they key would have to be stored in an accessible way), this isn't really that much of a protection.


    The best way would probably be to have part of the SWF-logic on the server, and not give access to that part from third party hosts (by using the crossdomain file).

    ReplyDelete
  3. Look into the idea of wrapping main inside a type of preloader, and putting main into a secure dir on the server. I cant remember how this gets around the cache problem, but it had to do with how the wrapper loads main.

    Something like this:

    // preloader.as (embedded in fla)
    var imageLoader:Loader;

    function randomNumber(low:Number=NaN, high:Number=NaN):Number
    {
    var low:Number = low;
    var high:Number = high;

    if(isNaN(low))
    {
    throw new Error("low must be defined");
    }
    if(isNaN(high))
    {
    throw new Error("high must be defined");
    }

    return Math.round(Math.random() * (high - low)) + low;
    }
    function loadImage(url:String):void {
    imageArea.visible=false;
    preloader.visible = true;
    // Set properties on my Loader object
    imageLoader = new Loader();
    imageLoader.load(new URLRequest(url));
    imageLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, imageLoading);
    imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
    imageArea.addChild(imageLoader);
    }
    // DOIT!
    loadImage("main.sw?"+randomNumber(1000,10000)); //NOT A TYPO!
    //loadImage("main.swf"+randomNumber(1000,10000);


    function imageLoaded(e:Event):void {
    // Hide Preloader
    preloader.visible = false;
    }

    function imageLoading(e:ProgressEvent):void {
    // Get current download progress
    var loaded:Number = e.bytesLoaded / e.bytesTotal;
    // Send progress info to "preloader" movie clip
    preloader.SetProgress(loaded);
    }

    /// this is main.sw //NOT A TYPO
    <?php
    // Tried this - abandoned
    // session_start();
    //
    // if(isset($_SESSION["flash"])) {
    // $referrer = $_SERVER["HTTP_REFERER"];
    // $referrer = parse_url($referrer);
    // if($referrer["host"] != $_SESSION["flash"]) {
    // echo "Permission denied.";
    // exit();
    // }
    // } else {
    // echo "Permission denied.";
    // exit();
    // }
    //
    // unset($_SESSION["flash"]);

    header("Content-type: application/x-shockwave-flash");
    readfile("/secure/main.swf");
    ?>

    // main.as
    public function onCreationComplete(event:Event):void{
    Security.allowDomain( "*" );
    Security.loadPolicyFile( "crossdomain.xml" );
    }

    // crossdomain.xml
    <?xml version="1.0"?>
    <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
    <cross-domain-policy>
    <allow-access-from domain="*" />
    </cross-domain-policy>


    That should get you started. The idea here was to prevent anyone from getting main on their machine- I am not sure if it worked.

    ReplyDelete
  4. I use this method to determine if I am on dev or production in my config files.

    var lc:LocalConnection = new LocalConnection();
    switch ( lc.domain ){
    case "myDomain.com":
    case "":// local file reference for dev
    case "localhost":// local file reference for dev
    case "dev.mydomain.com":// local file reference for dev
    break;
    default:
    // unknown domain do crash the app here
    }

    ReplyDelete