Index: modules/openid/openid.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/openid/openid.module,v
retrieving revision 1.77
diff -u -9 -p -r1.77 openid.module
--- modules/openid/openid.module	22 Mar 2010 18:55:45 -0000	1.77
+++ modules/openid/openid.module	23 Mar 2010 19:18:34 -0000
@@ -363,23 +363,30 @@ function openid_openid_discovery_method_
 /**
  * OpenID discovery method: perform an XRI discovery.
  *
  * @see http://openid.net/specs/openid-authentication-2_0.html#discovery
  * @see hook_openid_discovery_method_info()
  */
 function _openid_xri_discovery($claimed_id) {
   if (_openid_is_xri($claimed_id)) {
     // Resolve XRI using a proxy resolver (Extensible Resource Identifier (XRI)
-    // Resolution Version 2.0, section 11.2).
+    // Resolution Version 2.0, section 11.2 and 14.3).
     $xrds_url = variable_get('xri_proxy_resolver', 'http://xri.net/') . rawurlencode($claimed_id) . '?_xrd_r=application/xrds+xml';
     $services = _openid_xrds_discovery($xrds_url);
-    foreach ($services as &$service) {
-      $service['claimed_id'] = openid_normalize((string)$service['xrd']->children(OPENID_NS_XRD)->CanonicalID);
+    foreach ($services as $i => &$service) {
+      $status = $service['xrd']->children(OPENID_NS_XRD)->Status;
+      if ($status && $status->attributes()->cid == 'verified') {
+        $service['claimed_id'] = openid_normalize((string)$service['xrd']->children(OPENID_NS_XRD)->CanonicalID);
+      }
+      else {
+        // Ignore service if CanonicalID could not be verified.
+        unset($services[$i]);
+      }
     }
     return $services;
   }
 }
 
 /**
  * OpenID discovery method: perform a XRDS discovery.
  *
  * @see http://openid.net/specs/openid-authentication-2_0.html#discovery
Index: modules/openid/openid.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/openid/openid.test,v
retrieving revision 1.16
diff -u -9 -p -r1.16 openid.test
--- modules/openid/openid.test	22 Mar 2010 18:48:20 -0000	1.16
+++ modules/openid/openid.test	23 Mar 2010 19:18:34 -0000
@@ -57,18 +57,22 @@ class OpenIDFunctionalTest extends Drupa
 
     // Identifier is the URL of an HTML page containing a <meta http-equiv=...>
     // element that contains the URL of an XRDS document.
     $this->addIdentity(url('openid-test/yadis/http-equiv', array('absolute' => TRUE)), 2);
 
     // Identifier is an XRI. Resolve using our own dummy proxy resolver.
     variable_set('xri_proxy_resolver', url('openid-test/yadis/xrds/xri', array('absolute' => TRUE)) . '/');
     $this->addIdentity('@example*résumé;%25', 2, 'http://example.com/user');
 
+    // Make sure that unverified CanonicalID are not trusted.
+    variable_set('openid_test_canonical_id_status', 'bad value');
+    $this->addIdentity('@example*résumé;%25', 2, FALSE);
+
     // HTML-based discovery:
     // If the User-supplied Identifier is a URL of an HTML page, the page may
     // contain a <link rel=...> element containing the URL of the OpenID
     // Provider Endpoint. OpenID 1 and 2 describe slightly different formats.
 
     // OpenID Authentication 1.1, section 3.1:
     $this->addIdentity(url('openid-test/html/openid1', array('absolute' => TRUE)), 1);
 
     // OpenID Authentication 2.0, section 7.3.3:
@@ -171,33 +175,40 @@ class OpenIDFunctionalTest extends Drupa
 
   /**
    * Add OpenID identity to user's profile.
    *
    * @param $identity
    *   The User-supplied Identifier.
    * @param $version
    *   The protocol version used by the service.
    * @param $claimed_id
-   *   The expected Claimed Identifier returned by the OpenID Provider.
+   *   The expected Claimed Identifier returned by the OpenID Provider, or FALSE
+   *   if the discovery is expected to fail.
    */
   function addIdentity($identity, $version = 2, $claimed_id = NULL) {
-    $this->drupalGet('user/' . $this->web_user->uid . '/openid');
     $edit = array('openid_identifier' => $identity);
-    $this->drupalPost(NULL, $edit, t('Add an OpenID'));
+    $this->drupalPost('user/' . $this->web_user->uid . '/openid', $edit, t('Add an OpenID'));
+
+    if ($claimed_id === FALSE) {
+      $this->assertRaw(t('Sorry, that is not a valid OpenID. Ensure you have spelled your ID correctly.'), t('Invalid identity was rejected.'));
+      return;
+    }
 
     // OpenID 1 used a HTTP redirect, OpenID 2 uses a HTML form that is submitted automatically using JavaScript.
     if ($version == 2) {
-      // Manually submit form because SimpleTest is not able to execute JavaScript.
-      $this->assertRaw('<script type="text/javascript">document.getElementById("openid-redirect-form").submit();</script>', t('JavaScript form submission found.'));
+      // Check we are on the OpenID redirect form.
+      $this->assertTitle(t('OpenID redirect'), t('OpenID redirect page was displayed.'));
+
+      // Submit form to the OpenID Provider Endpoint.
       $this->drupalPost(NULL, array(), t('Send'));
     }
 
-    if (!$claimed_id) {
+    if (!isset($claimed_id)) {
       $claimed_id = $identity;
     }
     $this->assertRaw(t('Successfully added %identity', array('%identity' => $claimed_id)), t('Identity %identity was added.', array('%identity' => $identity)));
   }
 
   /**
    * Test OpenID auto-registration with e-mail verification disabled.
    */
   function testRegisterUserWithoutEmailVerification() {
Index: modules/openid/tests/openid_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/openid/tests/openid_test.module,v
retrieving revision 1.11
diff -u -9 -p -r1.11 openid_test.module
--- modules/openid/tests/openid_test.module	22 Mar 2010 18:48:20 -0000	1.11
+++ modules/openid/tests/openid_test.module	23 Mar 2010 19:18:35 -0000
@@ -84,18 +84,19 @@ function openid_test_yadis_xrds() {
         if (arg(4) . '/' . arg(5) != '@example*résumé;%25?_xrd_r=application/xrds xml') {
           drupal_not_found();
         }
       }
     }
     drupal_add_http_header('Content-Type', 'application/xrds+xml');
     print '<?xml version="1.0" encoding="UTF-8"?>
       <xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)">
         <XRD>
+          <Status cid="' . check_plain(variable_get('openid_test_canonical_id_status', 'verified')) . '"/>
           <ProviderID>xri://@</ProviderID>
           <CanonicalID>http://example.com/user</CanonicalID>
           <Service>
             <Type>http://example.com/this-is-ignored</Type>
           </Service>
           <Service priority="10">
             <Type>http://specs.openid.net/auth/2.0/signon</Type>
             <Type>http://openid.net/srv/ax/1.0</Type>
             <URI>' . url('openid-test/endpoint', array('absolute' => TRUE)) . '</URI>
