Esempio n. 1
0
def test_success():
    store = {}

    def do_callback(message):
        assert message['To'] == '*****@*****.**'

        url = message.get_payload().strip()
        args = parse_args(url)

        assert url.startswith('http://example/cb/')

        result = handler.check_callback(url, parse_args(url), {})
        LOGGER.info('check_callback(%s,%s): %s', url, args, result)

        assert isinstance(result, disposition.Verified)
        store['result'] = result

        store['is_done'] = result.identity

    handler = email_addr.EmailAddress(do_callback,
                                      'some data',
                                      tokens.DictStore(store),
                                      email_template_text='{url}')

    result = handler.initiate_auth('mailto:[email protected]',
                                   'http://example/cb/', '/redir')
    LOGGER.info('initiate_auth: %s', result)
    assert isinstance(result, disposition.Notify)
    assert result.cdata == 'some data'

    assert store['result'].identity == 'mailto:[email protected]'
    assert store['result'].redir == '/redir'
Esempio n. 2
0
def test_please_wait(mocker):
    token_store = tokens.DictStore()
    pending = {}
    mock_send = mocker.MagicMock()
    handler = email_addr.EmailAddress(mock_send,
                                      "this is data",
                                      token_store,
                                      expires_time=60,
                                      pending_storage=pending)

    mock_time = mocker.patch('time.time')
    assert mock_send.call_count == 0
    mock_time.return_value = 10

    # First auth should call mock_send
    handler.initiate_auth('mailto:[email protected]', 'http://example/', 'blop')
    assert mock_send.call_count == 1
    assert '*****@*****.**' in pending
    token_value = pending['*****@*****.**']

    # Second auth should not
    handler.initiate_auth('mailto:[email protected]', 'http://example/', 'blop')
    assert mock_send.call_count == 1
    assert '*****@*****.**' in pending
    assert token_value == pending['*****@*****.**']

    # Using the link should remove the pending item
    handler.check_callback('http://example/', {'t': pending['*****@*****.**']},
                           {})
    assert '*****@*****.**' not in pending

    # Next auth should call mock_send again
    handler.initiate_auth('mailto:[email protected]', 'http://example/', 'blop')
    assert mock_send.call_count == 2
    assert '*****@*****.**' in pending
    assert token_value != pending['*****@*****.**']
    token_value = pending['*****@*****.**']

    # Timing out the token should cause it to send again
    mock_time.return_value = 1000
    handler.initiate_auth('mailto:[email protected]', 'http://example/', 'blop')
    assert mock_send.call_count == 3
    assert '*****@*****.**' in pending
    assert token_value != pending['*****@*****.**']
    token_value = pending['*****@*****.**']

    # And anything else that removes the token from the token_store should as well
    token_store.remove(pending['*****@*****.**'])
    handler.initiate_auth('mailto:[email protected]', 'http://example/', 'blop')
    assert mock_send.call_count == 4
    assert token_value != pending['*****@*****.**']
    token_value = pending['*****@*****.**']
Esempio n. 3
0
def test_basics():
    handler = email_addr.EmailAddress(None, None, tokens.DictStore())
    assert handler.service_name == 'Email'
    assert handler.url_schemes
    assert 'email' in handler.description
    assert handler.cb_id == 'e'
    assert handler.logo_html[0][1] == 'Email'

    assert handler.handles_url('*****@*****.**') == 'mailto:[email protected]'
    assert handler.handles_url('mailto:[email protected]') == 'mailto:[email protected]'

    # email addresses must be well-formed
    assert not handler.handles_url('mailto:foobar.baz')

    # don't support other schemas
    assert not handler.handles_url('email:[email protected]')
    assert not handler.handles_url('@[email protected]')
    assert not handler.handles_url('https://example.com/')

    # handle leading/trailing spaces correctly
    assert handler.handles_url('  [email protected]') == 'mailto:[email protected]'
    assert handler.handles_url('mailto:  [email protected]') == 'mailto:[email protected]'
    assert handler.handles_url('mailto:[email protected]  ') == 'mailto:[email protected]'

    # but don't allow embedded spaces
    assert not handler.handles_url('   foo @bar.baz')

    # email address must be valid
    assert not handler.handles_url(' asdf[]@poiu_foo.baz!')

    # don't allow bang-paths
    assert not handler.handles_url('bang!path!is!fun!bob')
    assert not handler.handles_url('bang.com!path!is!fun!bob')
    assert not handler.handles_url('[email protected]')

    # strip out non-email-address components
    assert handler.handles_url(
        'mailto:[email protected]?subject=pwned') == 'mailto:[email protected]'

    # handle case correctly
    assert handler.handles_url(
        'MailtO:[email protected]') == 'mailto:[email protected]'
Esempio n. 4
0
def test_failures(mocker):
    store = {}
    pending = {}

    def accept(message):
        url = message.get_payload().strip()
        pending[message['To']] = url

    handler = email_addr.EmailAddress(accept,
                                      'some data',
                                      tokens.DictStore(store),
                                      10,
                                      email_template_text='{url}')

    # must be well-formed mailto: URL
    for malformed in ('*****@*****.**', 'http://foo.bar/', 'mailto:blahblahblah'):
        assert 'Malformed' in str(
            handler.initiate_auth(malformed, 'http://example.cb/',
                                  '/malformed'))

    # check for missing or invalid tokens
    assert 'Missing token' in str(handler.check_callback('foo', {}, {}))
    assert 'Invalid token' in str(
        handler.check_callback('foo', {'t': 'bogus'}, {}))

    def initiate(addr, redir):
        result = handler.initiate_auth('mailto:' + addr, 'http://example/',
                                       redir)
        assert isinstance(result, disposition.Notify)
        assert result.cdata == 'some data'

    def check_pending(addr):
        url = pending[addr]
        return handler.check_callback(url, parse_args(url), {})

    # check for timeout failure
    mock_time = mocker.patch('time.time')
    mock_time.return_value = 30

    assert len(store) == 0
    initiate('*****@*****.**', '/timeout')
    assert len(store) == 1

    mock_time.return_value = 20000

    result = check_pending('*****@*****.**')
    assert isinstance(result, disposition.Error)
    assert 'timed out' in result.message
    assert result.redir == '/timeout'
    assert len(store) == 0

    # check for replay attacks
    assert len(store) == 0
    initiate('*****@*****.**', '/replay')
    assert len(store) == 1
    result1 = check_pending('*****@*****.**')
    result2 = check_pending('*****@*****.**')
    assert len(store) == 0

    assert isinstance(result1, disposition.Verified)
    assert result1.identity == 'mailto:[email protected]'
    assert result1.redir == '/replay'
    assert isinstance(result2, disposition.Error)
    assert 'Invalid token' in str(result2)