Example #1
0
    def process_mail_creation(self, session, tid, data):
        user_id = data['user']['id']

        # Do not spool emails if the receiver has opted out of ntfns for this tip.
        if not data['tip']['enable_notifications']:
            log.debug("Discarding emails for %s due to receiver's preference.",
                      user_id)
            return

        # https://github.com/globaleaks/GlobaLeaks/issues/798
        # TODO: the current solution is global and configurable only by the admin
        sent_emails = self.state.get_mail_counter(user_id)
        if sent_emails >= self.state.tenant_cache[
                tid].notification.notification_threshold_per_hour:
            log.debug(
                "Discarding emails for receiver %s due to threshold already exceeded for the current hour",
                user_id)
            return

        self.state.increment_mail_counter(user_id)
        if sent_emails >= self.state.tenant_cache[
                tid].notification.notification_threshold_per_hour:
            log.info(
                "Reached threshold of %d emails with limit of %d for receiver %s",
                sent_emails,
                self.state.tenant_cache[tid].notification.
                notification_threshold_per_hour,
                user_id,
                tid=tid)

            # simply changing the type of the notification causes
            # to send the notification_limit_reached
            data['type'] = u'receiver_notification_limit_reached'

        data['node'] = self.serialize_config(session, 'node', tid,
                                             data['user']['language'])

        if data['node']['mode'] != u'whistleblowing.it':
            data['notification'] = self.serialize_config(
                session, 'notification', tid, data['user']['language'])
        else:
            data['notification'] = self.serialize_config(
                session, 'notification', 1, data['user']['language'])

        subject, body = Templating().get_mail_subject_and_body(data)

        # If the receiver has encryption enabled encrypt the mail body
        if data['user']['pgp_key_public']:
            pgpctx = PGPContext(self.state.settings.tmp_path)
            fingerprint = pgpctx.load_key(
                data['user']['pgp_key_public'])['fingerprint']
            body = pgpctx.encrypt_message(fingerprint, body)

        session.add(
            models.Mail({
                'address': data['user']['mail_address'],
                'subject': subject,
                'body': body,
                'tid': tid,
            }))
Example #2
0
    def process_mail_creation(self, session, tid, data):
        user_id = data['user']['id']
        language = data['user']['language']

        # Do not spool emails if the receiver has disabled notifications
        if not data['user']['notification'] or ('tip' in data and not data['tip']['enable_notifications']):
            log.debug("Discarding emails for %s due to receiver's preference.", user_id)
            return

        data['node'] = self.serialize_config(session, 'node', tid, language)

        data['submission_statuses'] = db_get_submission_statuses(session, tid, language)

        if data['node']['mode'] == 'default':
            data['notification'] = self.serialize_config(session, 'notification', tid, language)
        else:
            data['notification'] = self.serialize_config(session, 'notification', 1, language)

        subject, body = Templating().get_mail_subject_and_body(data)

        # If the receiver has encryption enabled encrypt the mail body
        if data['user']['pgp_key_public']:
            pgpctx = PGPContext(self.state.settings.tmp_path)
            fingerprint = pgpctx.load_key(data['user']['pgp_key_public'])['fingerprint']
            body = pgpctx.encrypt_message(fingerprint, body)

        session.add(models.Mail({
            'address': data['user']['mail_address'],
            'subject': subject,
            'body': body,
            'tid': tid,
        }))
Example #3
0
    def test_read_expirations(self):
        pgpctx = PGPContext()

        self.assertEqual(pgpctx.load_key(helpers.PGPKEYS['VALID_PGP_KEY1_PRV'])['expiration'],
                         datetime.utcfromtimestamp(0))

        self.assertEqual(pgpctx.load_key(helpers.PGPKEYS['EXPIRED_PGP_KEY_PUB'])['expiration'],
                         datetime.utcfromtimestamp(1391012793))
Example #4
0
def encrypt_file_with_pgp(state, fd, key, fingerprint, dest_path):
    """
    Encrypt the file for a specific key
    """
    pgpctx = PGPContext(state.settings.tmp_path)

    pgpctx.load_key(key)

    pgpctx.encrypt_file(fingerprint, fd, dest_path)
Example #5
0
    def format_and_send_mail(self, session, tid, user_desc, template_vars):
        subject, body = Templating().get_mail_subject_and_body(template_vars)

        if user_desc.get('pgp_key_public', ''):
            pgpctx = PGPContext(self.settings.tmp_path)
            fingerprint = pgpctx.load_key(user_desc['pgp_key_public'])['fingerprint']
            body = pgpctx.encrypt_message(fingerprint, body)

        db_schedule_email(session, tid, user_desc['mail_address'], subject, body)
Example #6
0
    def format_and_send_mail(self, session, tid, user_desc, template_vars):
        subject, body = Templating().get_mail_subject_and_body(template_vars)

        if user_desc.get('pgp_key_public', ''):
            pgpctx = PGPContext(self.settings.tmp_path)
            fingerprint = pgpctx.load_key(user_desc['pgp_key_public'])['fingerprint']
            body = pgpctx.encrypt_message(fingerprint, body)

        db_schedule_email(session, tid, user_desc['mail_address'], subject, body)
Example #7
0
    def schedule_exception_email(self, exception_text, *args):
        from globaleaks.transactions import schedule_email

        if not hasattr(self.tenant_cache[1], 'notification'):
            log.err(
                "Error: Cannot send mail exception before complete initialization."
            )
            return

        if self.exceptions_email_count >= self.settings.exceptions_email_hourly_limit:
            return

        exception_text = (exception_text % args) if args else exception_text

        sha256_hash = sha256(bytes(exception_text))

        if sha256_hash not in self.exceptions:
            self.exceptions[sha256_hash] = 0

        self.exceptions[sha256_hash] += 1
        if self.exceptions[sha256_hash] > 5:
            log.err(
                "Exception mail suppressed for (%s) [reason: threshold exceeded]",
                sha256_hash)
            return

        self.exceptions_email_count += 1

        mail_subject = "GlobaLeaks Exception"
        delivery_list = self.tenant_cache[
            1].notification.exception_delivery_list

        if self.settings.devel_mode:
            mail_subject += " [%s]" % self.settings.developer_name
            delivery_list = [("*****@*****.**",
                              '')]

        mail_body = bytes("Platform: %s (%s)\nVersion: %s\n\n%s" \
                          % (self.tenant_cache[1].hostname,
                             self.tenant_cache[1].onionservice,
                             __version__,
                             exception_text))

        for mail_address, pgp_key_public in delivery_list:
            # Opportunisticly encrypt the mail body. NOTE that mails will go out
            # unencrypted if one address in the list does not have a public key set.
            if pgp_key_public:
                pgpctx = PGPContext(self.settings.tmp_path)
                fingerprint = pgpctx.load_key(pgp_key_public)['fingerprint']
                mail_body = pgpctx.encrypt_message(fingerprint, mail_body)

            # avoid waiting for the notification to send and instead rely on threads to handle it
            schedule_email(1, mail_address, mail_subject, mail_body)
Example #8
0
    def format_and_send_mail(self, session, tid, user_desc, template_vars):
        subject, body = Templating().get_mail_subject_and_body(template_vars)

        if user_desc.get('pgp_key_public', ''):
            pgpctx = PGPContext(self.settings.tmp_path)
            fingerprint = pgpctx.load_key(user_desc['pgp_key_public'])['fingerprint']
            body = pgpctx.encrypt_message(fingerprint, body)

        session.add(models.Mail({
            'address': user_desc['mail_address'],
            'subject': subject,
            'body': body,
            'tid': tid,
        }))
Example #9
0
    def test_encrypt_message(self):
        fake_receiver_desc = {
            'pgp_key_public': helpers.PGPKEYS['VALID_PGP_KEY1_PUB'],
            'pgp_key_fingerprint': u'BFB3C82D1B5F6A94BDAC55C6E70460ABF9A4C8C1',
            'username': u'*****@*****.**',
        }

        pgpctx = PGPContext()
        pgpctx.load_key(helpers.PGPKEYS['VALID_PGP_KEY1_PRV'])

        encrypted_body = pgpctx.encrypt_message(fake_receiver_desc['pgp_key_fingerprint'],
                                                self.secret_content)

        self.assertEqual(str(pgpctx.gnupg.decrypt(encrypted_body)), self.secret_content)
Example #10
0
    def process_mail_creation(self, session, tid, data):
        user_id = data['user']['id']

        # Do not spool emails if the receiver has opted out of ntfns for this tip.
        if not data['tip']['enable_notifications']:
            log.debug("Discarding emails for %s due to receiver's preference.", user_id)
            return

        # https://github.com/globaleaks/GlobaLeaks/issues/798
        # TODO: the current solution is global and configurable only by the admin
        sent_emails = self.state.get_mail_counter(user_id)
        if sent_emails >= self.state.tenant_cache[tid].notification.notification_threshold_per_hour:
            log.debug("Discarding emails for receiver %s due to threshold already exceeded for the current hour",
                      user_id)
            return

        self.state.increment_mail_counter(user_id)
        if sent_emails >= self.state.tenant_cache[tid].notification.notification_threshold_per_hour:
            log.info("Reached threshold of %d emails with limit of %d for receiver %s",
                     sent_emails,
                     self.state.tenant_cache[tid].notification.notification_threshold_per_hour,
                     user_id,
                     tid=tid)

            # simply changing the type of the notification causes
            # to send the notification_limit_reached
            data['type'] = u'receiver_notification_limit_reached'

        data['node'] = self.serialize_config(session, 'node', tid, data['user']['language'])

        if data['node']['mode'] != u'whistleblowing.it':
            data['notification'] = self.serialize_config(session, 'notification', tid, data['user']['language'])
        else:
            data['notification'] = self.serialize_config(session, 'notification', 1, data['user']['language'])

        subject, body = Templating().get_mail_subject_and_body(data)

        # If the receiver has encryption enabled encrypt the mail body
        if data['user']['pgp_key_public']:
            pgpctx = PGPContext(self.state.settings.tmp_path)
            fingerprint = pgpctx.load_key(data['user']['pgp_key_public'])['fingerprint']
            body = pgpctx.encrypt_message(fingerprint, body)

        session.add(models.Mail({
            'address': data['user']['mail_address'],
            'subject': subject,
            'body': body,
            'tid': tid,
        }))
Example #11
0
def fsops_pgp_encrypt(state, sf, key, fingerprint):
    """
    Encrypt the file for a speficic key

    return
        path of encrypted file,
        length of the encrypted file
    """
    pgpctx = PGPContext(state.settings.tmp_path)

    pgpctx.load_key(key)

    with sf.open('r') as f:
        encrypted_file_path = os.path.join(os.path.abspath(state.settings.attachments_path), "pgp_encrypted-%s" % generateRandomKey(16))
        _, encrypted_file_size = pgpctx.encrypt_file(fingerprint, f, encrypted_file_path)

    return encrypted_file_path, encrypted_file_size
Example #12
0
    def schedule_exception_email(self, exception_text, *args):
        if not hasattr(self.tenant_cache[1], 'notification'):
            log.err("Error: Cannot send mail exception before complete initialization.")
            return

        if self.exceptions_email_count >= self.settings.exceptions_email_hourly_limit:
            return

        exception_text = (exception_text % args) if args else exception_text

        sha256_hash = sha256(exception_text.encode())

        if sha256_hash not in self.exceptions:
            self.exceptions[sha256_hash] = 0

        self.exceptions[sha256_hash] += 1
        if self.exceptions[sha256_hash] > 5:
            log.err("Exception mail suppressed for (%s) [reason: threshold exceeded]", sha256_hash)
            return

        self.exceptions_email_count += 1

        mail_subject = "GlobaLeaks Exception"
        delivery_list = self.tenant_cache[1].notification.exception_delivery_list

        mail_body = text_type("Platform: %s\nHost: %s (%s)\nVersion: %s\n\n%s"
                          % (self.tenant_cache[1].name,
                             self.tenant_cache[1].hostname,
                             self.tenant_cache[1].onionservice,
                             __version__,
                             exception_text))

        for mail_address, pgp_key_public in delivery_list:
            # Opportunisticly encrypt the mail body. NOTE that mails will go out
            # unencrypted if one address in the list does not have a public key set.
            if pgp_key_public:
                pgpctx = PGPContext(self.settings.tmp_path)
                fingerprint = pgpctx.load_key(pgp_key_public)['fingerprint']
                mail_body = pgpctx.encrypt_message(fingerprint, mail_body)

            # avoid waiting for the notification to send and instead rely on threads to handle it
            tw(db_schedule_email, 1, mail_address, mail_subject, mail_body)
Example #13
0
def parse_pgp_options(state, user, request):
    """
    Used for parsing PGP key infos and fill related user configurations.
    """
    pgp_key_public = request['pgp_key_public']
    remove_key = request['pgp_key_remove']

    k = None
    if not remove_key and pgp_key_public:
        pgpctx = PGPContext(state.settings.tmp_path)

        k = pgpctx.load_key(pgp_key_public)

    if k is not None:
        user.pgp_key_public = pgp_key_public
        user.pgp_key_fingerprint = k['fingerprint']
        user.pgp_key_expiration = k['expiration']
    else:
        user.pgp_key_public = ''
        user.pgp_key_fingerprint = ''
        user.pgp_key_expiration = datetime_null()
Example #14
0
def parse_pgp_options(user, request):
    """
    Used for parsing PGP key infos and fill related user configurations.
    """
    pgp_key_public = request['pgp_key_public']
    remove_key = request['pgp_key_remove']

    k = None
    if not remove_key and pgp_key_public:
        pgpctx = PGPContext(State.settings.tmp_path)

        k = pgpctx.load_key(pgp_key_public)

    if k is not None:
        user.pgp_key_public = pgp_key_public
        user.pgp_key_fingerprint = k['fingerprint']
        user.pgp_key_expiration = k['expiration']
    else:
        user.pgp_key_public = ''
        user.pgp_key_fingerprint = ''
        user.pgp_key_expiration = datetime_null()
Example #15
0
def encrypt_file_with_pgp(state, fd, key, fingerprint, dest_path):
    """
    Encrypt the file for a specific key
    """
    pgpctx = PGPContext(state.settings.tmp_path)

    pgpctx.load_key(key)

    pgpctx.encrypt_file(fingerprint, fd, dest_path)
Example #16
0
    def test_encrypt_file(self):
        file_src = os.path.join(os.getcwd(), 'test_plaintext_file.txt')
        file_dst = os.path.join(os.getcwd(), 'test_encrypted_file.txt')

        fake_receiver_desc = {
            'pgp_key_public': helpers.PGPKEYS['VALID_PGP_KEY1_PRV'],
            'pgp_key_fingerprint': u'BFB3C82D1B5F6A94BDAC55C6E70460ABF9A4C8C1',
            'username': u'*****@*****.**',
        }

        # these are the same lines used in delivery.py
        pgpctx = PGPContext()
        pgpctx.load_key(helpers.PGPKEYS['VALID_PGP_KEY1_PRV'])

        with open(file_src, 'w+') as f:
            f.write(self.secret_content)
            f.seek(0)

            pgpctx.encrypt_file(fake_receiver_desc['pgp_key_fingerprint'], f, file_dst)

        with open(file_dst, 'r') as f:
            self.assertEqual(str(pgpctx.gnupg.decrypt_file(f)), self.secret_content)