Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 556
  • Last Modified:

PHP / CAS interface question

I'm pretty new to PHP, so I'm hoping this is a relatively basic question for anyone who's familiar with common modules and such.

I've built a site that I want to link to a CAS server to authenticate users.  Everything's cool with whisking users to the CAS login page, authenticating them, and getting a service ticket appended as a $_GET variable.  However, I want to validate the ticket and receive their username as part of the server's validation response.  The reponse is in the form of a simple little PHP snippet, called validate.php.  

My problem is that the pre-written code I'm using to run the CAS authentication isn't properly receiving the validate.php data as a variable I can use.  So my question is this:

How do I receive the output validate.php file from the CAS server as an input variable in my code?  The current code uses
$req = new HTTP_Request('{CAS_SERVER}?ticket='.$ticket.'&service='.$this->_service);

where the HTTP_Request() function is from the PEAR package of the same name.  For whatever reason, $req comes back with nothing.  Again, if I type the argument passed to the function (a URL with a query appended to it), I get a correct validate.php in response . . .

Is there a better function/package I should look for to do this?  Like I said, I'm very new to using PHP, so I could well be missing something simple.
0
Zeek0
Asked:
Zeek0
  • 8
  • 7
1 Solution
 
Brian BushSolutions ArchitectCommented:
Obviously, you aren't showing all of your code, but it may be that you aren't
actually sending the request or getting the body. Try this:

<?php
require_once "HTTP/Request.php";

$req =& new HTTP_Request("{CAS_SERVER}?ticket=" . $ticket . "&service=" . $this->_service);
$response = $req->sendRequest();

if (PEAR::isError($response)) {
    echo $response->getMessage();
} else {
    echo $req->getResponseBody();
}
?>

If it doesn't work, at least it should give you a usable error message.

As for better ways to do this... You could use cURL, but PEAR packages
tend to be a good option for solid, feature rich interfaces. I would stick
with HTTP_REQUEST.

--brian
0
 
Zeek0Author Commented:
That's more or less how the code continues after what I posted.  The problem seems to be with receiving the data from the CAS server at all.  There are two options for validating the ticket, one which returns a file called validate.php that looks something like this:

yes
%username%

if the ticket is valid.  The other option returns an XML file that contains a %username%.

Again, if I manually enter the $URL from HTTP_Request($URL), I get the expected response from the server, for both the PHP reply and XML reply.  However, while trying to figure out where the problem is, I've thrown all kinds of echo statements into my code to see where the expected data is disappearing.  Even without the if statement you suggested, I  tried

$resp = $req->getResponseBody();
echo $resp;

which doesn't output anything.  I tried:

$req = new HTTP_Request($val_url);
echo $req;

which prints "object ID #2", which tells me at least *something* is there.  But then the getResponseBody (or getResponseCode() or getResponseHeader()) returns nothing.  

Nothing in this process is particularly detailed or complicated, but I simply can't seem to get the basic output from the CAS server anywhere onto my page.  
0
 
Brian BushSolutions ArchitectCommented:
One small thing. You want to have a & after the =.
That tells PHP to use a pointer rather than trying to copy the value.

The other thing is that you still aren't referencing the $req->sendRequest() command
in the code snippets you are posting.

Honestly, you're just not posting enough code for me to go on, but I can tell you that
this code works on my system in doing the same sort of thing you are looking for:

<?php
require_once "HTTP/Request.php";

$req =& new HTTP_Request("http://" . $_host . "/empdir/info.php?id=" . $_id);
$response = $req->sendRequest();

if (PEAR::isError($response)) {
    echo $response->getMessage();
} else {
    echo $req->getResponseBody();
}
?>

So, I guess what I want you to do is copy this code exactly into a new page on your system.
Then change the URL to what is appropriate for yours and tell me what it does.

I think that you may be getting the request and the response confused.
--brian
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Zeek0Author Commented:
Sorry, here's the function that's being called to verify the ticket (I removed some stuff just to save space, but the problem is occurring before the stuff I removed is even processed):

  public function verifyServiceTicket($ticket) {
    require_once('Request.php');
      
      $val_url = 'https://{%HOST%}?ticket='.$ticket.'&service='.$this->_service;   //I replaced my host with {%HOST%} - that's not a really dumb mistake
      $req = new HTTP_Request($val_url);
      $response = $req->sendRequest();
      echo "<br><a href=\"{$val_url}\">Validate ticket</a><br>";   //**when I click this link, I get a valid response from the CAS server**
      
    if (!PEAR::isError($req->sendRequest())) {
      $res = $req->getResponseBody();

        *** process the XML response from the server that should come through as $res ***

          }
    else {
      echo "ERROR: request returned an error value";                //This is the output I get every time I run it, which should only come up if $res is an error
      return false;
    }

  }


I've tried taking out the if/else stuff (which always goes to the 'else' portion when I run the code as-is).

I have to note that the code was pre-written by someone else, so presumably it was debugged and worked on his system.  I'm running IIS 6 with PHP 5 ISAPI, and I'm wondering if there's a setting or permission somewhere that I need to set in order for the contents of an URL to be passed as a string . . .  

I'm no expert, but the code looks perfectly okay to me.  I can't tell exactly what's breaking, but it's apparent that the CAS server's response is being interpreted as an empty string - unless there's a mistake I'm not seeing in the function's request to the server, the reply is being mishandled somewhere and I can't figure out where.

0
 
Zeek0Author Commented:
also, I changed to the =& on the new HTTP_Request() call, but no change.
0
 
Brian BushSolutions ArchitectCommented:
I'm not sure why the link is in there, but try this version of your code:

<?php
function verifyServiceTicket($ticket) {
    require_once("HTTP/Request.php");

    $val_url = 'https://{%HOST%}?ticket='.$ticket.'&service='.$this->_service;
    $req = new HTTP_Request($val_url);
    $response = $req->sendRequest();
    //echo "<br><a href=\"{$val_url}\">Validate ticket</a><br>";

    if (!PEAR::isError($req->sendRequest())) {
        $res = $req->getResponseBody();
        return $res; // You weren't actually returning the value in the code above.
    } else {
        echo "ERROR: request returned an error value";
        return false;
    }
}

var_dump(verifyServiceTicket("myTicket"));
?>

--brian
0
 
Zeek0Author Commented:
Here's what I've got for debugging purposes, to see where the flow is going:

  public function verifyServiceTicket($ticket) {
    require_once('Request.php');
      
      $val_url = '{%HOST%}?ticket='.$ticket.'&service='.$this->_service;
      $req =& new HTTP_Request($val_url);
      echo "<br><a href=\"{$val_url}\">Validate ticket</a><br>";
      $reply = $req->sendRequest();
      echo '<br>Reply:'.$reply.'<br>';
      
    if (!PEAR::isError($reply)) {
         echo "I'm in here!!!";
        
    }
    else {
        echo "ERROR: request returned an error value<br>{$req}";
        echo '<br>request:'.$req->sendRequest().'<br>';
                  return false;
    }

  }



And here's the output I get:



<br>
<a href="{%HOST%}?ticket={%TICKET%}&service={%SERVICE%}">Validate ticket</a><br>
<br>
Reply:Object id #5<br>
ERROR: request returned an error value<br>
Object id #2<br>
request:Object id #6<br>

So, the (!PEAR::isError($reply)) is returning false and I'm not even getting into that loop.  And when I try to output what's being returned from the server, the best I can get is these "Object id #" things.  

The response from {%HOST%} when I click the link looks like this:

<cas:serviceResponse xmlns:cas='{%SOMEOTHERHOST%}'>
      <cas:authenticationSuccess>
            <cas:user>{%USERNAME%}</cas:user>


      </cas:authenticationSuccess>
</cas:serviceResponse>



0
 
Brian BushSolutions ArchitectCommented:
OK. Let's cut out all of the extra and see what happens.
Create a blank php script and just put this code in it:

<?php
require_once("HTTP/Request.php");

// Use a full URL with the variables resolved to a concrete test value, if possible.
$_req =& new HTTP_Request("https://cas.myhost.com?ticket=12345&service=myService");
$_req->sendRequest();

echo "<PRE>\n" . var_dump($_req) . "</PRE>\n";
?>

You should get a very detailed break down of your request object.
It may help you debug your issue better.

If this doesn't give you enough, we should try pointing your HTTP_Request to some other URL
to make sure it is functioning correctly.
--brian
0
 
Brian BushSolutions ArchitectCommented:
This is a good for a neutral third-party site test:

<?php
require_once("HTTP/Request.php");

$_req =& new HTTP_Request("http://finance.yahoo.com/d/quotes.csv?s=IBM&f=sl1d1t1c1ohgv&e=.csv");
$_req->setProxy("proxy.myCompany.com", 8080, "<user>", "<password>"); // If you have to go through a proxy
$_req->sendRequest();

echo "<PRE>\n";
var_dump($_req);
echo "</PRE>\n";
?>

If that works for you, then so should the CAS stuff.
Also good if you want to grab your company's stock quote.

--brian
0
 
Zeek0Author Commented:
Still nothing.  I talked to the person who wrote the code I started with, and it was developed on Apache, where it works fine.  I've tried switching over to the cURL methods, pointing to different pages, and otherwise tooling with the code any way I can think of, and I still can't get anything but NULL as the contents of the string that is supposed to hold the XML response from the CAS server.  As far as I can tell, everything is linking up fine, but the variable that's supposed to contain the response doesn't get filled.

I've been using var_dump and print_r all over the place to check the state of the different classes, and the URL always looks correct, but I CANNOT get the page's contents into the string.  If I can enter the URL into my browser and get a valid response, I can't see how I'd need to do go through some complicated connection process.

Is there a PHP setting that I should double check?  I've tried running process explorer on the server to check for any kind of permission issue there, but found nothing.  
0
 
Brian BushSolutions ArchitectCommented:
You said it works under Apache.

Have you tested this code using Apache on the same server?
If so, what web server are you using that is not working?

If not, what are the differences between the server that
works and the one you are using now? For instance,
manufacturer, OS, patch level, etc.

--brian
0
 
Zeek0Author Commented:
I'm running updated IIS 6.  I don't have Apache installed, so I can't test with that.  
0
 
Brian BushSolutions ArchitectCommented:
Then you are running this on Windows Server 2003 as well.
What version of PHP are you using?
I will try to test it on my end.

In the meantime, I can tell you that I have heard rumblings
of a bug with timeouts over SSL and other bugs possibly
related to timeouts on IIS 6. I am still trying to track down
a resolution to those.

--brian
0
 
Zeek0Author Commented:
I'm using PHP 5.1.2 / IIS 6.0 and WinS2k3.

currently, the timeout is set to none.  I'll try setting it to something like 5 seconds and see what happens.  Given the simplicity of the exchange, that should be more than enough.
0
 
Zeek0Author Commented:
Well, I got it working and it turns out that it was IIS 6 causing the problem.  I'll give you the points because you provided some helpful suggestions regarding the PHP aspects and helped me eliminate the script as the root of the problem.

For whatever reason, the process pooling or whatever in IIS6 doesn't work correctly.  I set my server to run in IIS 5 isolation mode, with the application security set to "low (IIS service)" and it works.  I tried setting IIS 6's defaull app pool to run under the system account and even that didn't work.

I've scoured google and found a few people with similar issues, but nothing yet regarding why this problem occurs or how to fix it.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 8
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now