Show
Ignore:
Timestamp:
03/12/09 09:11:52 (9 months ago)
Author:
fumiakiy
Message:

Merged sockfish to trunk. "svn merge -r3114:3527 http://code.sixapart.com/svn/movabletype/branches/sockfish/ ."

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/extlib/Net/OpenID/Consumer.pm

    r2758 r3531  
    44use Carp (); 
    55use LWP::UserAgent; 
    6 use URI::Fetch 0.02; 
     6use Storable; 
    77 
    88############################################################################ 
     
    1010 
    1111use vars qw($VERSION); 
    12 $VERSION = "0.14"; 
     12$VERSION = "1.03"; 
    1313 
    1414use fields ( 
    15     'cache',           # the Cache object sent to URI::Fetch 
     15    'cache',           # a Cache object to store HTTP responses and associations 
    1616    'ua',              # LWP::UserAgent instance to use 
    1717    'args',            # how to get at your args 
     
    3030use Net::OpenID::Yadis; 
    3131use Net::OpenID::IndirectMessage; 
     32use Net::OpenID::URIFetch; 
    3233 
    3334use MIME::Base64 (); 
     
    204205} 
    205206 
    206  
    207207sub _get_url_contents { 
    208208    my Net::OpenID::Consumer $self = shift; 
    209     my  ($url, $final_url_ref, $hook) = @_; 
     209    my ($url, $final_url_ref, $hook) = @_; 
    210210    $final_url_ref ||= do { my $dummy; \$dummy; }; 
    211211 
    212     my $ures = URI::Fetch->fetch($url, 
    213                                  UserAgent        => $self->ua, 
    214                                  Cache            => $self->cache, 
    215                                  ContentAlterHook => $hook, 
    216                                  ) 
    217         or return $self->_fail("url_fetch_error", "Error fetching URL: " . URI::Fetch->errstr); 
    218  
    219     # who actually uses HTTP gone response status?  uh, nobody. 
    220     if ($ures->status == URI::Fetch::URI_GONE()) { 
    221         return $self->_fail("url_gone", "URL is no longer available"); 
    222     } 
    223  
    224     my $res = $ures->http_response; 
    225     $$final_url_ref = $res->request->uri->as_string; 
    226  
    227     return $ures->content; 
     212    my $res = Net::OpenID::URIFetch->fetch($url, $self, $hook); 
     213 
     214    $$final_url_ref = $res->final_uri; 
     215 
     216    return $res ? $res->content : undef; 
    228217} 
    229218 
     
    241230    }; 
    242231 
    243     my $doc = $self->_get_url_contents($url, $final_url_ref, $trim_hook) or 
    244         return; 
     232    my $doc = $self->_get_url_contents($url, $final_url_ref, $trim_hook) || ''; 
    245233 
    246234    # find <head> content of document (notably: the first head, if an attacker 
     
    403391    my $primary_only = delete $opts{primary_only} ? 1 : 0; 
    404392 
     393    my $force_version = delete $opts{force_version}; 
     394 
    405395    Carp::croak("Unknown option(s) ".join(', ', keys(%opts))) if %opts; 
    406396 
     
    429419 
    430420    # First we Yadis service discovery 
    431     my $yadis = Net::OpenID::Yadis->new(ua => $self->{ua}); 
     421    my $yadis = Net::OpenID::Yadis->new(consumer => $self); 
    432422    if ($yadis->discover($url)) { 
    433423        # FIXME: Currently we don't ever do _find_semantic_info in the Yadis 
     
    484474            if (@versions) { 
    485475                foreach my $version (@versions) { 
     476                    next if defined($force_version) && $force_version != $version; 
    486477                    foreach my $uri (@$service_uris) { 
    487478                        push @discovered_endpoints, { 
     
    531522        if ($sem_info) { 
    532523            if ($sem_info->{"openid2.provider"}) { 
    533                 push @discovered_endpoints, { 
    534                     uri => $sem_info->{"openid2.provider"}, 
    535                     version => 2, 
    536                     final_url => $final_url, 
    537                     delegate => $sem_info->{"openid2.local_id"}, 
    538                     sem_info => $sem_info, 
    539                     mechanism => "HTML", 
    540                 }; 
     524                unless (defined($force_version) && $force_version != 2) { 
     525                    push @discovered_endpoints, { 
     526                        uri => $sem_info->{"openid2.provider"}, 
     527                        version => 2, 
     528                        final_url => $final_url, 
     529                        delegate => $sem_info->{"openid2.local_id"}, 
     530                        sem_info => $sem_info, 
     531                        mechanism => "HTML", 
     532                    }; 
     533                } 
    541534            } 
    542535            if ($sem_info->{"openid.server"}) { 
    543                 push @discovered_endpoints, { 
    544                     uri => $sem_info->{"openid.server"}, 
    545                     version => 1, 
    546                     final_url => $final_url, 
    547                     delegate => $sem_info->{"openid.delegate"}, 
    548                     sem_info => $sem_info, 
    549                     mechanism => "HTML", 
    550                 }; 
     536                unless (defined($force_version) && $force_version != 1) { 
     537                    push @discovered_endpoints, { 
     538                        uri => $sem_info->{"openid.server"}, 
     539                        version => 1, 
     540                        final_url => $final_url, 
     541                        delegate => $sem_info->{"openid.delegate"}, 
     542                        sem_info => $sem_info, 
     543                        mechanism => "HTML", 
     544                    }; 
     545                } 
    551546            } 
    552547        } 
     
    652647    my $signed   = $self->message("signed"); 
    653648 
     649    my $possible_endpoints; 
     650    my $server; 
     651    my $claimed_identity; 
     652 
    654653    my $real_ident; 
    655654    if ($self->_message_version == 1) { 
    656655        $real_ident = $self->args("oic.identity") || $a_ident; 
     656 
     657        # In version 1, we have to assume that the primary server 
     658        # found during discovery is the one sending us this message. 
     659        $possible_endpoints = $self->_discover_acceptable_endpoints($real_ident, force_version => 1); 
     660 
     661        if ($possible_endpoints && @$possible_endpoints) { 
     662            $possible_endpoints = [ $possible_endpoints->[0] ]; 
     663            $server = $possible_endpoints->[0]{uri}; 
     664        } 
     665        else { 
     666            # We just fall out of here and bail out below for having no endpoints. 
     667        } 
    657668    } 
    658669    else { 
    659670        $real_ident = $self->message("claimed_id") || $a_ident; 
     671 
     672        # In version 2, the OP tells us its URL. 
     673        $server = $self->message("op_endpoint"); 
     674        $possible_endpoints = $self->_discover_acceptable_endpoints($real_ident, force_version => 2); 
     675 
     676        # FIXME: It kinda sucks that the above will always do both Yadis and HTML discovery, even though 
     677        # in most cases only one will be in use. 
     678    } 
     679 
     680    $self->_debug("Server is $server"); 
     681 
     682    unless ($possible_endpoints && @$possible_endpoints) { 
     683        return $self->_fail("no_identity_server"); 
    660684    } 
    661685 
     
    678702    } 
    679703 
    680     my $claimed_identity = $self->claimed_identity($real_ident); 
    681     return $self->_fail("no_identity_server") unless $claimed_identity; 
    682  
    683     # NOTE: Currently we're expecting the "primary" OP -- that is, the one that "wins" 
    684     # when we do discovery -- to be the one that sends the response. Since we currently 
    685     # don't support falling back to other providers in the XRD case, this should always 
    686     # be a valid assumption unless this assersion request is unsolicited. 
    687     # We'll also fail if the identifier's provider priorities are twiddled between 
    688     # request and response, but that's unlikely enough that we're just going to ignore it. 
    689  
    690     my $final_url = $claimed_identity->claimed_url; 
    691  
    692     # OpenID 2.0 wants us to exclude the fragment part of the URL when doing equality checks 
    693     my $a_ident_nofragment = $a_ident; 
    694     my $real_ident_nofragment = $real_ident; 
    695     my $final_url_nofragment = $final_url; 
    696     if ($self->_message_version >= 2) { 
    697         $a_ident_nofragment =~ s/\#.*$//x; 
    698         $real_ident_nofragment =~ s/\#.*$//x; 
    699         $final_url_nofragment =~ s/\#.*$//x; 
    700     } 
    701     return $self->_fail("unexpected_url_redirect") unless $final_url_nofragment eq $real_ident_nofragment; 
    702  
    703     my $server = $claimed_identity->identity_server; 
    704  
    705     # Protocol version must match 
    706     return $self->_fail("protocol_version_incorrect") unless $claimed_identity->protocol_version == $self->_message_version; 
    707  
    708     # if openid.delegate was used, check that it was done correctly 
    709     if ($a_ident_nofragment ne $real_ident_nofragment) { 
    710         my $delegate = $claimed_identity->delegated_url; 
     704    my $last_error = undef; 
     705 
     706    foreach my $endpoint (@$possible_endpoints) { 
     707        my $final_url = $endpoint->{final_url}; 
     708        my $endpoint_uri = $endpoint->{uri}; 
     709        my $delegate = $endpoint->{delegate}; 
     710 
     711        my $error = sub { 
     712            $self->_debug("$endpoint_uri not acceptable: ".$_[0]); 
     713            $last_error = $_[0]; 
     714        }; 
     715 
     716        # The endpoint_uri must match our $server 
     717        if ($endpoint_uri ne $server) { 
     718            $error->("server_not_allowed"); 
     719            next; 
     720        } 
     721 
     722        # OpenID 2.0 wants us to exclude the fragment part of the URL when doing equality checks 
    711723        my $a_ident_nofragment = $a_ident; 
    712         $a_ident_nofragment =~ s/\#.*$//; 
    713         $self->_debug("verified_identity: verifying delegate $delegate for $a_ident_nofragment"); 
    714         return $self->_fail("bogus_delegation") unless $delegate eq $a_ident; 
     724        my $real_ident_nofragment = $real_ident; 
     725        my $final_url_nofragment = $final_url; 
     726        if ($self->_message_version >= 2) { 
     727            $a_ident_nofragment =~ s/\#.*$//x; 
     728            $real_ident_nofragment =~ s/\#.*$//x; 
     729            $final_url_nofragment =~ s/\#.*$//x; 
     730        } 
     731        unless ($final_url_nofragment eq $real_ident_nofragment) { 
     732            $error->("unexpected_url_redirect"); 
     733            next; 
     734        } 
     735 
     736        # Protocol version must match 
     737        unless ($endpoint->{version} == $self->_message_version) { 
     738            $error->("protocol_version_incorrect"); 
     739            next; 
     740        } 
     741 
     742        # if openid.delegate was used, check that it was done correctly 
     743        if ($a_ident_nofragment ne $real_ident_nofragment) { 
     744            unless ($delegate eq $a_ident_nofragment) { 
     745                $error->("bogus_delegation"); 
     746                next; 
     747            } 
     748        } 
     749 
     750        # If we've got this far then we've found the right endpoint. 
     751 
     752        $claimed_identity =  Net::OpenID::ClaimedIdentity->new( 
     753            identity         => $endpoint->{final_url}, 
     754            server           => $endpoint->{uri}, 
     755            consumer         => $self, 
     756            delegate         => $endpoint->{delegate}, 
     757            protocol_version => $endpoint->{version}, 
     758            semantic_info    => $endpoint->{sem_info}, 
     759        ); 
     760        last; 
     761 
     762    } 
     763 
     764    unless ($claimed_identity) { 
     765        # We failed to find a good endpoint in the above loop, so 
     766        # lets bail out. 
     767        return $self->_fail($last_error); 
    715768    } 
    716769 
     
    721774 
    722775    my %signed_fields;   # key (without openid.) -> value 
     776 
     777    # Auth 2.0 requires certain keys to be signed. 
     778    if ($self->_message_version >= 2) { 
     779        my %signed_fields = map {$_ => 1} split /,/, $signed; 
     780        my %unsigned_fields; 
     781        # these fields must be signed unconditionally 
     782        foreach my $f (qw/op_endpoint return_to response_nonce assoc_handle/) { 
     783            $unsigned_fields{$f}++ if !$signed_fields{$f}; 
     784        } 
     785        # these fields must be signed if present 
     786        foreach my $f (qw/claimed_id identity/) { 
     787            next unless $self->args("openid.$f"); 
     788            $unsigned_fields{$f}++ if !$signed_fields{$f}; 
     789        } 
     790        if (%unsigned_fields) { 
     791            return $self->_fail( 
     792                "unsigned_field", 
     793                "Field(s) must be signed: " . join(", ", keys %unsigned_fields) 
     794            ); 
     795        } 
     796    } 
    723797 
    724798    if ($assoc) { 
     
    13471421This is free software. IT COMES WITHOUT WARRANTY OF ANY KIND. 
    13481422 
     1423=head1 MAILING LIST 
     1424 
     1425The Net::OpenID family of modules has a mailing list powered 
     1426by Google Groups. For more information, see 
     1427http://groups.google.com/group/openid-perl . 
     1428 
    13491429=head1 SEE ALSO 
    13501430