views:

65

answers:

2

Hello, I'm developing an application for a client's website. Here's the story, this company uses an application/HDD called synology that is basically an HDD box connected to the internet and gives access to files to clients with pre-created accounts. This interface is written in CGI and I have no access to the box (different network and location from the website).

What we wanna do is allow a login form from the main website (I'm building) bypassing (at least to the users :D) the application login form.

I obviously can't do a jQuery ajax request to different domains, it won't work. So what I did is

1) Form on the website working with jQuery:

$("#login_submit").click(function(){
    var username= $("input#login_username").val();
    var passwd= $("input#login_passwd").val();
    var post_string = "username=" + username + "&passwd=" + passwd ;
    $.ajax({
        type : "POST",
        url: "login.php",
        data : post_string,
        success: function(response){

            if (response){
                $('.result').html("OK");
                window.location = "http://XX.XX.net:5000/webman/index.cgi";
             }
             else {
                 $('.result').html("INVALID");
             }
        }
    })
    return false;
}

2) Call a login.php page on submit passing user and password via POST, the PHP page makes a HTTP POST request to the remote synology server and gives me a response in JSON apparently (?) that I convert to a PHP array so that I can see if the "success" key is true or false, if true the jquery code will print an OK message and redirect to the remote sylonogy server where I can access my data-logged in!

<?php
function do_post_request($url, $data, $optional_headers = null)
{
  $params = array('http' => array(
              'method' => 'POST',
              'content' => $data
            ));
  if ($optional_headers !== null) {
    $params['http']['header'] = $optional_headers;
  }
  $ctx = stream_context_create($params);
  $fp = @fopen($url, 'rb', false, $ctx);
  if (!$fp) {
    throw new Exception("Problem with $url, $php_errormsg");
  }
  $response = @stream_get_contents($fp);
  if ($response === false) {
    throw new Exception("Problem reading data from $url, $php_errormsg");
  }
  return $response;
}

if ($_SERVER['REQUEST_METHOD'] == "POST"){
    $username = $_POST["username"];
    $passwd = $_POST["passwd"];

    $response =json_decode(do_post_request($url = "http://XX.XX.net:5000/webman/login.cgi", $data = "username=".$username."&passwd=".$passwd), true);

            if($response["success"]){
                $send = true;
            }
            else {
                $send = false;
            }
        echo  $send;
}

The problem here is that the login.cgi page is supposed to set a session cookie for that server but using that PHP request it just won't. It will give a response but it won't set the cookie to the browser. Do you have any idea what I can do to imitate a POST browser request and set the cookie while maintaining that jquery function? maybe I should set some headers? If make a simple form to that login.cgi as "action" the session cookie is but the user will of course remain on that page that I can't change since I have no access to it.

A: 

If you are making this request in PHP, then the cookie is going to your server, not to the client. You cannot set a cookie for another domain from your application, so this won't work. You need to stick to a client-side method.

Brad
any suggestion? if I can't let the cookie be set by the remote server than I don't see any solution :(
Sandro Antonucci
Can't you make all of the necessary requests client-side with Javascript?
Brad
No because I can't make requests via JS to different domains
Sandro Antonucci
+1  A: 

Use stream_get_meta_data() to extract the HTTP headers returned from the server<->synology requests. If the rest of your code is working properly with the proper synology urls/parameters, the headers returned from the login request should contain the session cookie necessary to authenticate further requests on the synology box.

You can then store this in the session file for the server<->user communications, and haul it out for subsequent requests.

comment followup:

yes, exactly. The curl-initiated requests are done purely server-side and will not involve the client at all. While you CAN retrieve the synology session/access cookie via curl, there's no way to send that cookie to the client such that it'll look like it came from the synology box directly.

For instance, let's pretend the synology response cookie header looks like this:

Set-Cookie: sessionID=blahblahblah; path=/; domain=synologybox.com

You extract the session ID and forward it to the client:

setcookie("sessionID", 'blahblahblah', 360000, '/');

then the client will store it as having come from yourserver.com, not synologybox.com. Also, you wouldn't be able to set the domain via the setcookie call:

setcookie("sessionID", 'blahblahblah', 360000, '/', 'synologybox.com')

This won't work, as the server<->client request is coming from yourserver.com, which is nowhere near the same as synologbox.com.

Without any access to the synology box to hack in extra authentication facilities, you're most likely stuck having to build an entire proxy version of the synology interface.

Marc B
yes the server does return the correct cookie (checked with stream_get_meta_data() but I don't know what to do with it! I still need the cookie to be set for synology domain. Isn't there a way to send to the client the header received in PHP?
Sandro Antonucci
Sure, just loop over the headers received from the synology box and output them via the `header()` function so they go out to the client. But then you're still stuck with the fact that the client will set the synology cookie as having come from your server. There's no way you can make the client set that cookie so it looks like it came from the synology box, since it's coming from your PHP script which is a completely different machine/domain.
Marc B
I understand :( i was reading that you can accept cookies with cURL but I suppose from what you're saying that "accept" doesn't mean it will be set as coming from the synology box, am I right?
Sandro Antonucci
Thanks a lot Marc B! You got the best answer mark :) Best support ever :) I asked access for the synology box.thank you again
Sandro Antonucci