コード例 #1
0
ファイル: openid2rp.py プロジェクト: Carreau/pypi-legacy
def associate(services, url):
    '''Create an association (OpenID section 8) between RP and OP.
    Return response as a dictionary.'''
    req_data = {
        'openid.ns':"http://specs.openid.net/auth/2.0",
        'openid.mode':"associate",
        'openid.assoc_type':"HMAC-SHA1",
        'openid.session_type':"no-encryption",
        }
    if url.startswith('http:'):
        # Use DH exchange
        req_data['openid.session_type'] = "DH-SHA1"
        # Private key: random number between 1 and dh_prime-1
        priv = random.SystemRandom().randrange(1, dh_prime - 1)
        # Public key: 2^priv mod prime
        pubkey = pow(2L, priv, dh_prime)
        dh_public_base64 = base64.b64encode(btwoc(pubkey))
        # No need to send key and generator
        req_data['openid.dh_consumer_public'] = dh_public_base64
    if is_compat_1x(services):
        # 14.2.1: clear session_type in 1.1 compatibility mode
        if req_data['openid.session_type'] == "no-encryption":
            req_data['openid.session_type'] = ''
        del req_data['openid.ns']
    res = urllib.urlopen(url, b(urllib.urlencode(req_data)))
    try:
        if res.getcode() != 200:
            raise ValueError("OpenID provider refuses connection with status %s" % res.getcode())
        data = parse_response(res.read())
    except ValueError:
        endpoint = OpenIDServiceEndpoint.fromOPEndpointURL(url)
        store = MemoryStore()
        consumer = GenericConsumer(store)
        try:
            assoc = consumer._requestAssociation(endpoint, req_data['openid.assoc_type'], req_data['openid.session_type'])
            data = {
                'assoc_handle': assoc.handle,
                'expires_in': assoc.lifetime,
                'mac_key': oidutil.toBase64(assoc.secret),
            }
        except ServerError:
            data = {
                'error': 'Server %s refused its suggested association type: session_type=%s, assoc_type=%s' % (url, req_data['openid.assoc_type'], req_data['openid.session_type']),
            }
    if 'error' in data:
        raise ValueError, "associate failed: "+data['error']
    if url.startswith('http:'):
        enc_mac_key = b(data.get('enc_mac_key'))
        if not enc_mac_key:
            raise ValueError, "Provider protocol error: not using DH-SHA1"
        enc_mac_key = base64.b64decode(enc_mac_key)
        dh_server_public = unbtwoc(base64.b64decode(b(data['dh_server_public'])))
        # shared secret: sha1(2^(server_priv*priv) mod prime) xor enc_mac_key
        shared_secret = btwoc(pow(dh_server_public, priv, dh_prime))
        shared_secret = hashlib.sha1(shared_secret).digest()
        if len(shared_secret) != len(enc_mac_key):
            raise ValueError, "incorrect DH key size"
        # Fake mac_key result
        data['mac_key'] = b(base64.b64encode(string_xor(enc_mac_key, shared_secret)))
    return data
コード例 #2
0
class IdResCheckForFieldsTest(TestIdRes):
    def setUp(self):
        self.consumer = GenericConsumer(None)

    def mkSuccessTest(openid_args, signed_list):
        def test(self):
            message = Message.fromOpenIDArgs(openid_args)
            message.setArg(OPENID_NS, 'signed', ','.join(signed_list))
            self.consumer._idResCheckForFields(message)
        return test

    test_openid1Success = mkSuccessTest(
        {'return_to':'return',
         'assoc_handle':'assoc handle',
         'sig':'a signature',
         'identity':'someone',
         },
        ['return_to', 'identity'])

    test_openid2Success = mkSuccessTest(
        {'ns':OPENID2_NS,
         'return_to':'return',
         'assoc_handle':'assoc handle',
         'sig':'a signature',
         'op_endpoint':'my favourite server',
         'response_nonce':'use only once',
         },
        ['return_to', 'response_nonce', 'assoc_handle', 'op_endpoint'])

    test_openid2Success_identifiers = mkSuccessTest(
        {'ns':OPENID2_NS,
         'return_to':'return',
         'assoc_handle':'assoc handle',
         'sig':'a signature',
         'claimed_id':'i claim to be me',
         'identity':'my server knows me as me',
         'op_endpoint':'my favourite server',
         'response_nonce':'use only once',
         },
        ['return_to', 'response_nonce', 'identity',
         'claimed_id', 'assoc_handle', 'op_endpoint'])

    def mkMissingFieldTest(openid_args):
        def test(self):
            message = Message.fromOpenIDArgs(openid_args)
            try:
                self.consumer._idResCheckForFields(message)
            except ProtocolError, why:
                self.failUnless(why[0].startswith('Missing required'))
            else:
コード例 #3
0
    def setUp(self):
        self.store = GoodAssocStore()
        self.consumer = GenericConsumer(self.store)
        self.server_url = "http://idp.unittest/"
        CatchLogs.setUp(self)

        claimed_id = 'bogus.claimed'

        self.message = Message.fromOpenIDArgs(
            {'mode': 'id_res',
             'return_to': 'return_to (just anything)',
             'identity': claimed_id,
             'assoc_handle': 'does not matter',
             'sig': GOODSIG,
             'response_nonce': mkNonce(),
             'signed': 'identity,return_to,response_nonce,assoc_handle,claimed_id,op_endpoint',
             'claimed_id': claimed_id,
             'op_endpoint': self.server_url,
             'ns':OPENID2_NS,
             })

        self.endpoint = OpenIDServiceEndpoint()
        self.endpoint.server_url = self.server_url
        self.endpoint.claimed_id = claimed_id
        self.consumer._checkReturnTo = lambda unused1, unused2 : True
コード例 #4
0
    def run():
        trust_root = consumer_url

        consumer = GenericConsumer(store)
        setConsumerSession(consumer)

        request = consumer.begin(endpoint)
        return_to = consumer_url

        m = request.getMessage(trust_root, return_to, immediate)

        redirect_url = request.redirectURL(trust_root, return_to, immediate)

        parsed = urlparse.urlparse(redirect_url)
        qs = parsed[4]
        q = parseQuery(qs)
        new_return_to = q['openid.return_to']
        del q['openid.return_to']
        assert q == {
            'openid.mode':mode,
            'openid.identity':delegate_url,
            'openid.trust_root':trust_root,
            'openid.assoc_handle':fetcher.assoc_handle,
            }, (q, user_url, delegate_url, mode)

        assert new_return_to.startswith(return_to)
        assert redirect_url.startswith(server_url)

        parsed = urlparse.urlparse(new_return_to)
        query = parseQuery(parsed[4])
        query.update({
            'openid.mode':'id_res',
            'openid.return_to':new_return_to,
            'openid.identity':delegate_url,
            'openid.assoc_handle':fetcher.assoc_handle,
            })

        assoc = store.getAssociation(server_url, fetcher.assoc_handle)

        message = Message.fromPostArgs(query)
        message = assoc.signMessage(message)
        info = consumer.complete(message, request.endpoint, new_return_to)
        assert info.status == SUCCESS, info.message
        assert info.identity_url == user_url
コード例 #5
0
ファイル: consumer.py プロジェクト: abtain/Heraldry
    def run():
        trust_root = consumer_url

        consumer = GenericConsumer(store)
        request = consumer.begin(endpoint)

        return_to = consumer_url
        redirect_url = request.redirectURL(trust_root, return_to, immediate)

        parsed = urlparse.urlparse(redirect_url)
        qs = parsed[4]
        q = parseQuery(qs)
        new_return_to = q['openid.return_to']
        del q['openid.return_to']
        assert q == {
            'openid.mode':mode,
            'openid.identity':delegate_url,
            'openid.trust_root':trust_root,
            'openid.assoc_handle':fetcher.assoc_handle,
            }, (q, user_url, delegate_url, mode)

        assert new_return_to.startswith(return_to)
        assert redirect_url.startswith(server_url)

        query = {
            'nonce':request.return_to_args['nonce'],
            'openid.mode':'id_res',
            'openid.return_to':new_return_to,
            'openid.identity':delegate_url,
            'openid.assoc_handle':fetcher.assoc_handle,
            }

        assoc = store.getAssociation(server_url, fetcher.assoc_handle)
        assoc.addSignature(['mode', 'return_to', 'identity'], query)

        info = consumer.complete(query, request.endpoint)
        assert info.status == SUCCESS, info.message
        assert info.identity_url == user_url
コード例 #6
0
 def setUp(self):
     self.store = memstore.MemoryStore()
     self.consumer = GenericConsumer(self.store)
     self.endpoint = OpenIDServiceEndpoint()
コード例 #7
0
 def setUp(self):
     self.consumer = GenericConsumer(None)
コード例 #8
0
class TestCompleteMissingSig(unittest.TestCase, CatchLogs):

    def setUp(self):
        self.store = GoodAssocStore()
        self.consumer = GenericConsumer(self.store)
        self.server_url = "http://idp.unittest/"
        CatchLogs.setUp(self)

        claimed_id = 'bogus.claimed'

        self.message = Message.fromOpenIDArgs(
            {'mode': 'id_res',
             'return_to': 'return_to (just anything)',
             'identity': claimed_id,
             'assoc_handle': 'does not matter',
             'sig': GOODSIG,
             'response_nonce': mkNonce(),
             'signed': 'identity,return_to,response_nonce,assoc_handle,claimed_id,op_endpoint',
             'claimed_id': claimed_id,
             'op_endpoint': self.server_url,
             'ns':OPENID2_NS,
             })

        self.endpoint = OpenIDServiceEndpoint()
        self.endpoint.server_url = self.server_url
        self.endpoint.claimed_id = claimed_id
        self.consumer._checkReturnTo = lambda unused1, unused2 : True

    def tearDown(self):
        CatchLogs.tearDown(self)


    def test_idResMissingNoSigs(self):
        def _vrfy(resp_msg, endpoint=None):
            return endpoint

        self.consumer._verifyDiscoveryResults = _vrfy
        r = self.consumer.complete(self.message, self.endpoint, None)
        self.failUnlessSuccess(r)


    def test_idResNoIdentity(self):
        self.message.delArg(OPENID_NS, 'identity')
        self.message.delArg(OPENID_NS, 'claimed_id')
        self.endpoint.claimed_id = None
        self.message.setArg(OPENID_NS, 'signed', 'return_to,response_nonce,assoc_handle,op_endpoint')
        r = self.consumer.complete(self.message, self.endpoint, None)
        self.failUnlessSuccess(r)


    def test_idResMissingIdentitySig(self):
        self.message.setArg(OPENID_NS, 'signed', 'return_to,response_nonce,assoc_handle,claimed_id')
        r = self.consumer.complete(self.message, self.endpoint, None)
        self.failUnlessEqual(r.status, FAILURE)


    def test_idResMissingReturnToSig(self):
        self.message.setArg(OPENID_NS, 'signed', 'identity,response_nonce,assoc_handle,claimed_id')
        r = self.consumer.complete(self.message, self.endpoint, None)
        self.failUnlessEqual(r.status, FAILURE)


    def test_idResMissingAssocHandleSig(self):
        self.message.setArg(OPENID_NS, 'signed', 'identity,response_nonce,return_to,claimed_id')
        r = self.consumer.complete(self.message, self.endpoint, None)
        self.failUnlessEqual(r.status, FAILURE)


    def test_idResMissingClaimedIDSig(self):
        self.message.setArg(OPENID_NS, 'signed', 'identity,response_nonce,return_to,assoc_handle')
        r = self.consumer.complete(self.message, self.endpoint, None)
        self.failUnlessEqual(r.status, FAILURE)


    def failUnlessSuccess(self, response):
        if response.status != SUCCESS:
            self.fail("Non-successful response: %s" % (response,))
コード例 #9
0
 def setUp(self):
     store = object()
     self.consumer = GenericConsumer(store)
コード例 #10
0
class TestReturnToArgs(unittest.TestCase):
    """Verifying the Return URL paramaters.
    From the specification "Verifying the Return URL"::

        To verify that the "openid.return_to" URL matches the URL that is
        processing this assertion:

         - The URL scheme, authority, and path MUST be the same between the
           two URLs.

         - Any query parameters that are present in the "openid.return_to"
           URL MUST also be present with the same values in the
           accepting URL.

    XXX: So far we have only tested the second item on the list above.
    XXX: _verifyReturnToArgs is not invoked anywhere.
    """

    def setUp(self):
        store = object()
        self.consumer = GenericConsumer(store)

    def test_returnToArgsOkay(self):
        query = {
            'openid.mode': 'id_res',
            'openid.return_to': 'http://example.com/?foo=bar',
            'foo': 'bar',
            }
        # no return value, success is assumed if there are no exceptions.
        self.consumer._verifyReturnToArgs(query)

    def test_returnToArgsUnexpectedArg(self):
        query = {
            'openid.mode': 'id_res',
            'openid.return_to': 'http://example.com/',
            'foo': 'bar',
            }
        # no return value, success is assumed if there are no exceptions.
        self.failUnlessRaises(ProtocolError,
                              self.consumer._verifyReturnToArgs, query)

    def test_returnToMismatch(self):
        query = {
            'openid.mode': 'id_res',
            'openid.return_to': 'http://example.com/?foo=bar',
            }
        # fail, query has no key 'foo'.
        self.failUnlessRaises(ValueError,
                              self.consumer._verifyReturnToArgs, query)

        query['foo'] = 'baz'
        # fail, values for 'foo' do not match.
        self.failUnlessRaises(ValueError,
                              self.consumer._verifyReturnToArgs, query)


    def test_noReturnTo(self):
        query = {'openid.mode': 'id_res'}
        self.failUnlessRaises(ValueError,
                              self.consumer._verifyReturnToArgs, query)

    def test_completeBadReturnTo(self):
        """Test GenericConsumer.complete()'s handling of bad return_to
        values.
        """
        return_to = "http://some.url/path?foo=bar"

        # Scheme, authority, and path differences are checked by
        # GenericConsumer._checkReturnTo.  Query args checked by
        # GenericConsumer._verifyReturnToArgs.
        bad_return_tos = [
            # Scheme only
            "https://some.url/path?foo=bar",
            # Authority only
            "http://some.url.invalid/path?foo=bar",
            # Path only
            "http://some.url/path_extra?foo=bar",
            # Query args differ
            "http://some.url/path?foo=bar2",
            "http://some.url/path?foo2=bar",
            ]

        m = Message(OPENID1_NS)
        m.setArg(OPENID_NS, 'mode', 'cancel')
        m.setArg(BARE_NS, 'foo', 'bar')
        endpoint = None

        for bad in bad_return_tos:
            m.setArg(OPENID_NS, 'return_to', bad)
            self.failIf(self.consumer._checkReturnTo(m, return_to))

    def test_completeGoodReturnTo(self):
        """Test GenericConsumer.complete()'s handling of good
        return_to values.
        """
        return_to = "http://some.url/path"

        good_return_tos = [
            (return_to, {}),
            (return_to + "?another=arg", {(BARE_NS, 'another'): 'arg'}),
            (return_to + "?another=arg#fragment", {(BARE_NS, 'another'): 'arg'}),
            ("HTTP"+return_to[4:], {}),
            (return_to.replace('url','URL'), {}),
            ("http://some.url:80/path", {}),
            ("http://some.url/p%61th", {}),
            ("http://some.url/./path", {}),
            ]

        endpoint = None

        for good, extra in good_return_tos:
            m = Message(OPENID1_NS)
            m.setArg(OPENID_NS, 'mode', 'cancel')

            for ns, key in extra:
                m.setArg(ns, key, extra[(ns, key)])

            m.setArg(OPENID_NS, 'return_to', good)
            result = self.consumer.complete(m, endpoint, return_to)
            self.failUnless(isinstance(result, CancelResponse), \
                            "Expected CancelResponse, got %r for %s" % (result, good,))
コード例 #11
0
ファイル: openid2rp.py プロジェクト: waldyrious/pypi-legacy
def associate(services, url):
    '''Create an association (OpenID section 8) between RP and OP.
    Return response as a dictionary.'''
    req_data = {
        'openid.ns': "http://specs.openid.net/auth/2.0",
        'openid.mode': "associate",
        'openid.assoc_type': "HMAC-SHA1",
        'openid.session_type': "no-encryption",
    }
    if url.startswith('http:'):
        # Use DH exchange
        req_data['openid.session_type'] = "DH-SHA1"
        # Private key: random number between 1 and dh_prime-1
        priv = random.SystemRandom().randrange(1, dh_prime - 1)
        # Public key: 2^priv mod prime
        pubkey = pow(2L, priv, dh_prime)
        dh_public_base64 = base64.b64encode(btwoc(pubkey))
        # No need to send key and generator
        req_data['openid.dh_consumer_public'] = dh_public_base64
    if is_compat_1x(services):
        # 14.2.1: clear session_type in 1.1 compatibility mode
        if req_data['openid.session_type'] == "no-encryption":
            req_data['openid.session_type'] = ''
        del req_data['openid.ns']
    res = urllib.urlopen(url, b(urllib.urlencode(req_data)))
    try:
        if res.getcode() != 200:
            raise ValueError(
                "OpenID provider refuses connection with status %s" %
                res.getcode())
        data = parse_response(res.read())
    except ValueError:
        endpoint = OpenIDServiceEndpoint.fromOPEndpointURL(url)
        store = MemoryStore()
        consumer = GenericConsumer(store)
        try:
            assoc = consumer._requestAssociation(
                endpoint, req_data['openid.assoc_type'],
                req_data['openid.session_type'])
            data = {
                'assoc_handle': assoc.handle,
                'expires_in': assoc.lifetime,
                'mac_key': oidutil.toBase64(assoc.secret),
            }
        except ServerError:
            data = {
                'error':
                'Server %s refused its suggested association type: session_type=%s, assoc_type=%s'
                % (url, req_data['openid.assoc_type'],
                   req_data['openid.session_type']),
            }
    if 'error' in data:
        raise ValueError, "associate failed: " + data['error']
    if url.startswith('http:'):
        enc_mac_key = b(data.get('enc_mac_key'))
        if not enc_mac_key:
            raise ValueError, "Provider protocol error: not using DH-SHA1"
        enc_mac_key = base64.b64decode(enc_mac_key)
        dh_server_public = unbtwoc(
            base64.b64decode(b(data['dh_server_public'])))
        # shared secret: sha1(2^(server_priv*priv) mod prime) xor enc_mac_key
        shared_secret = btwoc(pow(dh_server_public, priv, dh_prime))
        shared_secret = hashlib.sha1(shared_secret).digest()
        if len(shared_secret) != len(enc_mac_key):
            raise ValueError, "incorrect DH key size"
        # Fake mac_key result
        data['mac_key'] = b(
            base64.b64encode(string_xor(enc_mac_key, shared_secret)))
    return data