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)
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'))
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
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'])
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))
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, '<#(!--'))
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))
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))