Пример #1
0
 def test_generate_challenge(self):
     """Test generating a challenge."""
     chal = str(Challenge.generate(self.user, self.user.fingerprint))
     self.assertIn('-----BEGIN PGP MESSAGE-----', chal)
     self.assertIn('-----END PGP MESSAGE-----', chal)
     chals = Challenge.query.all()
     self.assertEqual(self.user.chal_id, chals[1].id)
Пример #2
0
def login():
    if logged_in():
        return redirect(url_for('user',
                                fingerprint=session['fp']))

    if request.method == 'GET':
        if 'fingerprint' not in session:
            return None

    if request.method == 'POST':
        try:
            fp = request.form.get('fingerprint').replace(' ', '').lower()
            if not is_fingerprint(fp):
                flash(err_messages['not_fp'], 'error')
                return redirect(url_for('login'))
            user = User.query.filter(User.fingerprint == fp).one()
            session['fp'] = fp
            ciphertext = Challenge.generate(user, fp)
            return dict(ciphertext=ciphertext)
        except NoResultFound:
            flash(err_messages['no_account'], 'error')
        except Exception as e:
            flash(err_messages['generic'], 'error')
            app.logger.error(e)

        return redirect(url_for('login'))
Пример #3
0
def publish_canary(sigid_base64):
    canary = get_canary(sigid_base64)
    if canary is None:
        return page_not_found('canary')

    fp = canary.user.fingerprint

    if request.method == 'GET':
        ciphertext = Challenge.generate(canary, fp)
        return dict(canary=canary, ciphertext=ciphertext)

    if request.method == 'POST':
        """If the request originated from a logged in user's manage canary
        page, republish the canary."""
        if logged_in() and session['fp'] == fp:
            return republish_canary(canary)

        else:
            if Challenge.check(canary, request.form['decrypted'].strip()):
                return republish_canary(canary)
            else:
                flash(err_messages['decrypt_fail'], 'error')
                return None
Пример #4
0
def new_canary():
    if request.method == 'GET':
        return None

    if request.method == 'POST':
        try:
            signed = request.form['signedMessage']
            frequency_num = int(request.form['frequencyNum'])
            frequency_type = request.form['frequency']
        except KeyError:
            flash(err_messages['incomplete_form'], 'error')
            return None

        allowed_freqs = 'day', 'week', 'month'
        in_range = 1 <= frequency_num <= 100
        if frequency_type not in allowed_freqs or not in_range:
            flash(err_messages['invalid_freq'], 'error')
            return None
        # Get the frequency in days
        frequency = days(frequency_num, frequency_type)

        verified, err = gpg.verify(signed)
        # Start over if the message wasn't verified.
        if err and not verified:
            flash(err, 'error')
            return None

        fp = verified.fingerprint
        sigid_base64 = base64.urlsafe_b64encode(verified.signature_id)

        try:
            canary = Canary(sigid_base64, frequency, frequency_type)
            db_session.add(canary)
            db_session.commit()
        except IntegrityError:
            # Throw an error if a canary with that sigid already exists
            db_session.rollback()
            db_session.flush()
            flash(err_messages['dupe_canary'], 'error')
            return redirect(url_for('new_canary'))
        except Exception as e:
            db_session.rollback()
            db_session.flush()
            app.logger.error(e)
            """An unexpected database error should not reveal any
               error details to the user."""
            flash(err_messages['generic'], 'error')
            return None

        ciphertext = Challenge.generate(canary, fp)
        # TODO: This is sloppy.
        session['canary'] = dict(fp=verified.fingerprint.lower(),
                                 text=signed,
                                 uid=verified.username,
                                 keyid=verified.key_id,
                                 sigid_base64=sigid_base64,
                                 frequency=frequency,
                                 freq_type=frequency_type,
                                 ciphertext=str(ciphertext))

        flash(messages['verified'], 'message')
        return dict(canary=session['canary'])
Пример #5
0
def canary(sigid_base64):
    if request.method == 'GET':
        canary = get_canary(sigid_base64)
        if canary is None:
            return page_not_found('canary')

        pathstr = str(sigid_base64)
        path = os.path.join(app.config.get('CANARIES_DIR'), pathstr)
        f = open(path, 'r')
        text = f.read()
        f.close()
        return dict(canary=canary, text=text)

    if request.method == 'POST':
        if not is_sigid(sigid_base64):
            return redirect(url_for('index'))

        try:
            canary = Canary.query.filter(
                Canary.sigid_base64 == sigid_base64).one()
            decrypted = request.form['decrypted'].strip()
            if not Challenge.check(canary, decrypted):
                raise IncorrectChallengeException
        except KeyError:
            flash(err_messages['incomplete_form'], 'error')
            return None
        except IncorrectChallengeException:
            db_session.delete(canary)
            db_session.commit()
            flash(err_messages['decrypt_fail'], 'error')
            return redirect(url_for('new_canary'))
        except Exception as e:
            flash(err_messages['generic'], 'error')
            app.logger.error(e)
            return redirect(url_for('new_canary'))

        sess = session['canary']
        fp = sess['fp']
        try:
            user = User.query.filter(User.fingerprint == fp).one()
            """Update the existing user's key info, in case the username
            or email address has been edited since we last saw it."""
            user.update(canary['uid'])
        except NoResultFound:
            # Create a new user
            user = User(sess['keyid'], fp, sess['uid'])
            db_session.add(user)
            db_session.commit()

        canary.user_id = user.id
        canary.active = True
        db_session.commit()

        with app.app_context():
            text = sess['text']
            if app.testing:
                notify(canary, user, text)
            else:
                notify.delay(canary, user, text)

        pathstr = str(sigid_base64)
        path = os.path.join(app.config.get('CANARIES_DIR'), pathstr)

        with open(path, 'w') as f:
            f.write(text)
            f.close()

        flash(messages['published'], 'message')
        return redirect(url_for('canary', sigid_base64=sigid_base64))
Пример #6
0
 def test_check_invalid_challenge_format(self):
     """Test that submitting an incorrectly-formatted solution fails.
     """
     self.user.chal_id = self.chal.id
     self.assertFalse(Challenge.check(self.user, '<#(!--'))
Пример #7
0
 def test_check_invalid_challenge(self):
     """Test that submitting an invalid challenge solution fails."""
     self.user.chal_id = self.chal.id
     self.assertFalse(Challenge.check(self.user, '0' * 32))
Пример #8
0
 def test_check_valid_challenge(self):
     """Test that submitting a valid challenge solution succeeds."""
     self.user.chal_id = self.chal.id
     self.assertTrue(Challenge.check(self.user, self.sekrit))