Hi there,
It's blindly accepting parameters from POSTs and stuffing them straight into
the session, among other things, but the real problem appears to be that
you're making no attempt to verify that the inbound request matches the
users' domain.
You should set 'Use a domain specific issuer' in the control panel, pull the
Issuer out of the inbound request, and make sure that it matches.
Sam
On Wed, Jul 2, 2008 at 7:01 PM, yar <[EMAIL PROTECTED]> wrote:
>
> I have really very strange problem and need help
>
> We have for example 2 domains: ny.com and la.com. In google they are
> seperate accounts. In our db they are stored like [EMAIL PROTECTED],
> [EMAIL PROTECTED] etc
>
> We are using php sample for sso (not the latest version.
>
> Problem Case: User have 2 valid mailboxes in both domains:
> [EMAIL PROTECTED] and [EMAIL PROTECTED] All users logins to both domains
> from one web form
>
> 1. User logins to [EMAIL PROTECTED] and goes to its mailbox
> 2. User doesn't press signout button and returns back to login page
> 3. User logins to [EMAIL PROTECTED] and goes to its mailbox
> 4. User again doesn't press signout button and returns back to login
> page
> 5. (!!!) And now user try to login to somebody else's mailbox
> [EMAIL PROTECTED] with any password and he logins successfuly to the
> mailbox he doesn't own!
>
> I can imagine that here are problems with saml requests and sessions.
> Our programmer is several months is a former programmer and I don't
> have enouph php knowledge to fix it quickly.
>
> Can anybody suggets what goes wrong? Belong my process_response.php
> code (modified by former programmer slightly)
>
> Sorry code is too long for reading :) but I hope that a professional
> can find what is wrong quickly...
>
>
> <?php
> session_set_cookie_params (0, '/', '.mydomain.com');
> if (session_id() == "") {
> session_start();
> # setcookie('PHPSESSID', session_id(), 0, '/');
> }
>
> require_once 'saml_util.php';
>
> $domains = array(
> 'ny.com' => 'ny.com',
> 'la.com' => 'la.com',
> );
>
> $services = array (
> 'mail' => 'mail',
> 'calendar' => 'calendar',
> 'docs' => 'docs'
> );
>
> /**
> * The login method should either return null if the user is not
> * successfully authenticated, or the user's username if the user is
> * successfully authenticated.
> * @param string $username
> * @param string $password
> * @return string
> */
> function login($username, $password, $domain) {
> // Stage II: Update this method to call your authentication
> mechanism.
> // Return username for successful authentication. Return null
> // for failed authentication.
> $link = @mysql_connect('111.111.111.111', 'xxx', 'xxxxxxxxx');
> mysql_select_db('namedb', $link);
> $query = sprintf("SELECT Account FROM UserSession WHERE
> Account='%s' AND Password='%s'",
> mysql_real_escape_string("[EMAIL PROTECTED]"),
> mysql_real_escape_string($password));
> $result = mysql_query($query, $link);
> if (!$result) {
> return '';
> }
> $rows = mysql_num_rows($result);
> if ($rows == 1) {
> return $username;
> } else {
> return '';
> }
> }
>
> /**
> * Returns a SAML response with various elements filled in.
> * @param string $authenticatedUser The Google Apps username of the
> authenticated user
> * @param string $notBefore The ISO 8601 formatted date before which
> the
> response is invalid
> * @param string $notOnOrAfter The ISO 8601 formatted data after which
> the
> response is invalid
> * @param string $rsadsa 'rsa' if the response will be signed with RSA
> keys,
> 'dsa' for DSA keys
> * @param string $requestID The ID of the request we're responding to
> * @param string $destination The ACS URL that the response is
> submitted to
> * @return string XML SAML response.
> */
> function createSamlResponse($authenticatedUser, $notBefore,
> $notOnOrAfter,
> $rsadsa, $requestID, $destination) {
> global $domainName;
>
> $samlResponse = file_get_contents('templates/
> SamlResponseTemplate.xml');
> $samlResponse = str_replace('<USERNAME_STRING>',
> $authenticatedUser,
> $samlResponse);
> $samlResponse = str_replace('<RESPONSE_ID>', samlCreateId(),
> $samlResponse);
> $samlResponse = str_replace('<ISSUE_INSTANT>',
> samlGetDateTime(time()),
> $samlResponse);
> $samlResponse = str_replace('<AUTHN_INSTANT>',
> samlGetDateTime(time()),
> $samlResponse);
> $samlResponse = str_replace('<NOT_BEFORE>', $notBefore,
> $samlResponse);
> $samlResponse = str_replace('<NOT_ON_OR_AFTER>', $notOnOrAfter,
> $samlResponse);
> $samlResponse = str_replace('<ASSERTION_ID>', samlCreateId(),
> $samlResponse);
> $samlResponse = str_replace('<RSADSA>', strtolower($rsadsa),
> $samlResponse);
> $samlResponse = str_replace('<REQUEST_ID>', $requestID,
> $samlResponse);
> $samlResponse = str_replace('<DESTINATION>', $destination,
> $samlResponse);
> $samlResponse = str_replace('<ISSUER_DOMAIN>', $domainName,
> $samlResponse);
>
> return $samlResponse;
> }
>
> /**
> * Signs a SAML response with the given private key, and embeds the
> public key.
> * @param string $responseXmlString
> * @param string $pubKey
> * @param string $privKey
> * @return string
> */
> function signResponse($responseXmlString, $pubKey, $privKey) {
> // NOTE: You may want to point this function to a directory on your
> // web server that is suitable for temporary files and is not in
> your
> // web server path.
> global $error;
>
> // generate unique temporary filename
> $tempFileName = '/tmp/saml-response-' . samlCreateId() . '.xml';
> while (file_exists($tempFileName))
> $tempFileName = 'saml-response-' . samlCreateId() . '.xml';
>
> if (!$handle = fopen($tempFileName, 'w')) {
> echo 'Cannot open temporary file (' . $tempFileName . ')';
> exit;
> }
>
> if (fwrite($handle, $responseXmlString) === FALSE) {
> echo 'Cannot write to temporary file (' . $tempFileName . ')';
> exit;
> }
>
> fclose($handle);
>
> // The path to xmlsec/xmlsec1 may need to be adjusted here.
> // xmlsec supports many key types, which can be selected
> // by using other command-line parameters.
> $cmd = '/usr/local/bin/xmlsec1 --sign --privkey-pem ' . $privKey .
> ' --pubkey-der ' . $pubKey . ' --output ' . $tempFileName .
> '.out ' . $tempFileName;
> exec($cmd, $resp);
> unlink($tempFileName);
>
> $xmlResult = @file_get_contents($tempFileName . '.out');
> if (!$xmlResult) {
> $error = 'Unable to sign XML response. Please ensure that xmlsec
> is ' .
> 'installed, and check your keys.';
> return false;
> } else {
> unlink($tempFileName . '.out');
> return $xmlResult;
> }
> }
>
> if ($_POST['username']) {
> $user = $_POST['username'];
> $pass = $_POST['password'];
> $domain = $_POST['domain'];
> $service = $_POST['service'];
> if (!isset($service) || $service == '') {
> $service = 'mail';
> }
> $_SESSION['username'] = $user;
> $_SESSION['password'] = $pass;
> $_SESSION['domain'] = $domain;
> $_SESSION['service'] = $service;
> session_write_close();
> header("Location: http://$service.google.com/a/" .
> $domains[$domain]);
> exit();
> } else if($_GET['SAMLRequest'] != '') {
> $SAMLRequest =$_GET['SAMLRequest'];
> $username = $_SESSION['username'];
> $password = $_SESSION['password'];
> $domain = $_SESSION['domain'];
> $service = $_SESSION['service'];
> $relayStateURL = "http://$service.google.com/a/" .
> $domains[$domain];
> if ($SAMLRequest == '') {
> $error = 'Error: Unspecified SAML parameters.';
> } else {
> $requestXmlString = samlDecodeMessage($SAMLRequest);
> if (($requestXmlString == '')||($requestXmlString === FALSE)) {
> $error = 'Unable to decode SAML Request.';
> } else {
> $samlAttr = getRequestAttributes($requestXmlString);
> $issueInstant = $samlAttr['issueInstant'];
> $acsURL = $samlAttr['acsURL'];
> $providerName = $samlAttr['providerName'];
> $requestID = $samlAttr['requestID'];
>
> $login = login($username, $password, $domain);
> if ($login == '') {
> $error = 'Login Failed: Invalid user.';
> } else {
> // Acquire public and private DSA keys
>
> /*
> * Stage III: Update the DSA filenames to identify the
> locations of
> * the DSA/RSA keys that digitally sign SAML responses for your
> * domain. The keys included in the reference implementation
> sign SAML
> * responses for the psosamldemo.net domain.
> */
>
> $pubKey = 'keys/dsapubkey.der';
> $privKey = 'keys/dsaprivkey.pem';
> $keyType = 'dsa';
>
> // generate NotBefore and NotOnOrAfter dates
> $notBefore = samlGetDateTime(strtotime('-5 minutes'));
> $notOnOrAfter = samlGetDateTime(strtotime('+10 minutes'));
>
> // Sign XML containing user name with specified keys
> $responseXmlString = createSamlResponse($login, $notBefore,
> $notOnOrAfter,
> $keyType,
> $requestID,
> $acsURL);
> $samlResponse = signResponse($responseXmlString, $pubKey,
> $privKey);
> }
> }
> }
> if ($error != '') {
> if ($error == 'Login Failed: Invalid user.') {
> $error = 'error';
> } else {
> $error = 'error';
> }
> ?>
>
> <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://
> www.w3.or
> g/TR/xhtml1/loose.dtd">
> <html><head><title>Mysite</title><meta content="text/html;
> charset=utf-8" http-equiv=Content-Type /><meta http-equiv= "pragma"
> content="no-cache" />
>
> <meta http-equiv="Cache-Control" content="no-store" /><link
> rel="alternate" type="application/rss+xml" title="RSS 2.0" href="/rss/
> index.rss" />
>
> <style type="text/css" media="screen">@import url("/css/
> main.css");@import url("/css/in.css");.error {color: #a00;}</style></
> head>
>
> <body class="signup"><div id="minWidth"><div id="middle">
>
> <table class="tbl"><tr>
> <td id="leftCol"></td>
> <td id="centerCol"><div id="hot-news">
> <div class="topic_stories"><div id="main"><h1>Login</h1><form
> action="" method="post"><input type="hidden" name="service" value="<?
> echo htmlspecialchars($service) ?>">
>
> <table>
> <tr>
> <td><label for="username">Username:</label></td>
> <td><input name="username" id="username" value="<? echo
> htmlspecialchars($username) ?>" />
>
> @ <select class="select" name="domain"><? foreach (array('ny.com',
> 'la.com') as $host) { ?>
> <option value="<? echo $host ?>"<? if ($domain == $host) { ?>
> selected="selected"<? } ?>><? echo $host ?></option>
> <? } ?></select>
>
> <div class="error"><? if ($error) { ?><p><? echo $error ?></
> p><? } ?></div>
> </td>\
> </tr>
> <tr>
> <td><label for="password">Password:</label></td>
> <td><input id="password" name="password" type="password"></td>
> </tr>
> <tr>
> <td colspan="2"><input name="Login" value="Login" type="submit"></
> td>
> </tr>
> </table>
> </form>
> </div>
> </div>
> </div>
> </td>
>
> </div></body></html>
> <?
> } else if ($samlResponse != '') {
> ?>
> <html>
> <head>
> </head>
> <body onload="document.acsForm.submit()">
>
> <form name="acsForm" action="<?php echo $acsURL; ?>" method="post">
>
> <div style="display: none">
>
> <textarea rows=10 cols=80 name="SAMLResponse"><?php echo
> $samlResponse; ?></textarea>
> <textarea rows=10 cols=80 name="RelayState"><?php echo
> $relayStateURL; ?></textarea>
> </div>
>
> <noscript><input type="submit" value="Continue"></noscript></form></
> body></html>
>
> <?
> }
> } else {
> }
> ?>
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Google Apps APIs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/google-apps-apis?hl=en
-~----------~----~----~----~------~----~------~--~---