def add_fingerprint(self, from_user):
        '''
            Add the fingerprint for each type of crypto used to the email message header.
        '''

        try:
            encryption_software_list = contacts.get_encryption_names(from_user)
            if len(encryption_software_list) <= 0:
                self.log_message(
                    "Not adding fingerprint for {} because no crypto software".
                    format(from_user))
            else:
                for encryption_name in encryption_software_list:
                    fingerprint, __, active = contacts.get_fingerprint(
                        from_user, encryption_name)
                    if active and fingerprint is not None and len(
                            fingerprint.strip()) > 0:
                        self.email_message.add_header(
                            constants.PUBLIC_FINGERPRINT_HEADER.format(
                                encryption_name.upper()),
                            format_fingerprint(fingerprint))
                        self.log_message(
                            'added {} fingerprint'.format(encryption_name))
        except:
            record_exception()
            self.log_message('EXCEPTION - see syr.exception.log for details')
def add_contacts_crypto(contact,
                        encryption_software,
                        fingerprint=None,
                        source=None):
    '''
        Add a contact's crypto record.

        >>> contacts_crypto = add_contacts_crypto(None, None)
        >>> contacts_crypto is None
        True
    '''
    if contact is None or encryption_software is None:
        contacts_crypto = None
    else:
        if fingerprint is None:
            formatted_fingerprint = None
        else:
            formatted_fingerprint = format_fingerprint(fingerprint)

        contacts_crypto = ContactsCrypto.objects.create(
            contact=contact,
            encryption_software=encryption_software,
            fingerprint=formatted_fingerprint,
            source=source)
        log_message("created contact crypto for {}: {}".format(
            contact, contacts_crypto is not None))

    return contacts_crypto
Beispiel #3
0
 def save(self, *args, **kwargs):
     # maintain all addresses in lower case
     if not self.encryption_software or self.encryption_software is None:
         self.encryption_software = EnryptionSoftware.objects.all()[0]
     if self.fingerprint is not None:
         self.fingerprint = format_fingerprint(self.fingerprint)
     _log("saving a {} contact's crypto for {}".format(self.encryption_software, self.contact))
     super(ContactsCrypto, self).save(*args, **kwargs)
    def save(self):
        '''
            Save the fingerprint in the database.

            Test extreme case.
            >>> set_fingerprint_class = SetFingerprint(None)
            >>> set_fingerprint_class.save()
            False
        '''

        self.result_ok, self.crypto_name, self.email, self.key_plugin = prep_sync(self.contacts_encryption)
        if self.result_ok:
            try:
                # the contact's crypto record must exist or we'll get into an infinite loop
                # because whenever we add a contact's encryption for an email in our supported domain,
                # then this class is activated so we can complete the configuration
                if self.contacts_encryption is None:
                    self.result_ok = False
                    log_message('no contact encryption record for {}'.format(self.email))
                else:
                    fingerprint, expiration_date = self.key_plugin.get_fingerprint(self.email)
                    if fingerprint is None:
                        self.result_ok = False
                        log_message('no {} fingerprint found for {}'.format(self.crypto_name, self.email))
                    else:
                        self.result_ok = True
                        try:
                            fingerprint = format_fingerprint(fingerprint)
                            if (self.contacts_encryption.fingerprint is not None and
                                self.contacts_encryption.fingerprint != fingerprint):
                                log_message('replaced old fingerprint {} with {} for {}'.format(
                                    self.contacts_encryption.fingerprint, fingerprint, self.email))

                            # if we created the key, then be sure it's verified
                            if utils.email_in_domain(self.email):
                                if self.contacts_encryption.source is None and create_private_keys():
                                    self.contacts_encryption.source = AUTO_GENERATED
                                if self.contacts_encryption.source == AUTO_GENERATED:
                                    self.contacts_encryption.verified = True

                            self.contacts_encryption.fingerprint = fingerprint
                            self.contacts_encryption.save()
                            log_message('set {} fingerprint for {} in database: {}'.format(
                                self.crypto_name, self.email, fingerprint))
                        except IntegrityError as ie:
                            self.result_ok = False
                            if 'insert or update on table "mail_contactscrypto" violates foreign key constraint' in str(ie):
                                log_message('{} crypto key no longer exists for {}'.format(self.crypto_name, self.email))
                            else:
                                raise
            except Exception as exception:
                record_exception()
                log_message('EXCEPTION - see syr.exception.log for details')
                self.result_ok = False

        return self.result_ok
Beispiel #5
0
def notify_new_key_arrived(to_user, id_fingerprint_pairs):
    '''
        Notify user a new key arrived.

        >>> notify_new_key_arrived(None, None)
    '''

    if to_user is None or id_fingerprint_pairs is None or len(id_fingerprint_pairs) < 1:
        pass
    else:
        # use the first email address from the imported key
        try:
            email, __ = id_fingerprint_pairs[0]
        except:
            email = get_admin_email()

        header = i18n("To be safe, verify their key now by following these instructions:")
        tip = i18n("https://goodcrypto.com/qna/knowledge-base/user-verify-key")
        regular_notice = True
        if require_key_verified():
            regular_notice = False
            if is_metadata_address(email):
                domain = parse_domain(email)
                subject = i18n('Mail to {domain} cannot be sent until you verify the metadata key'.format(domain=domain))
                body = i18n("You received a public key for the email address(es) below. No one can send mail to users with this domain until you verify the key and update the database if it's okay. Otherwise, any mail sent to {domain} will be returned to the sender.".format(domain)),
            else:
                subject = i18n('Mail to {email} cannot be sent until you verify their key'.format(email=email))
                body = i18n("You received a public key for the email address(es) below. You cannot send mail until you check with the sender to verify the key and update the database if it's okay. Otherwise, any mail you send to this user will be returned to you."),
        else:
            if is_metadata_address(email):
                domain = parse_domain(email)
                subject = 'Metadata protection to {domain} is now ready'.format(domain=domain)
                body = 'Unless you disable metadata protection, all mail to {domain} will now have both metadata and content encrypted.'.format(
                        domain=domain)
            else:
                subject = i18n('Mail to {email} is now private'.format(email=email))
                body = i18n(
                  "The content of all messages to {email} will be protected.  ".format(email=email))
        body_text = "{}\n\n{} {}\n".format(
            body,
            header,
            tip)

        for (user_id, fingerprint) in id_fingerprint_pairs:
            body_text += "    {}: {}".format(user_id, format_fingerprint(fingerprint))

        if regular_notice:
            prefix = TAG_PREFIX
        else:
            prefix = TAG_WARNING

        notify_user(to_user, '{} - {}'.format(prefix, str(subject)), body_text)
Beispiel #6
0
def show_fingerprint(request, email, fingerprint, verified, active, page_title):
    ''' Show the fingerprint. '''

    log_message('showing {} fingerprint verified: {}'.format(email, verified))
    log_message('require verification {}'.format(options.require_key_verified()))

    template = 'mail/show_fingerprint.html'
    data = {'page_title': page_title,
            'fingerprint': format_fingerprint(fingerprint),
            'verified': verified,
            'active': active,
            'requires': options.require_key_verified()}
    return render_to_response(template, data, context_instance=RequestContext(request))
    def add_fingerprint(self, from_user):
        '''
            Add the fingerprint for each type of crypto used to the email message header.
        '''

        try:
            encryption_software_list = contacts.get_encryption_names(from_user)
            if len(encryption_software_list) <= 0:
                self.log_message("Not adding fingerprint for {} because no crypto software".format(from_user))
            else:
                for encryption_name in encryption_software_list:
                    fingerprint, __, active = contacts.get_fingerprint(from_user, encryption_name)
                    if active and fingerprint is not None and len(fingerprint.strip()) > 0:
                        self.email_message.add_header(constants.PUBLIC_FINGERPRINT_HEADER.format(
                            encryption_name.upper()), format_fingerprint(fingerprint))
                        self.log_message('added {} fingerprint'.format(encryption_name))
        except:
            record_exception()
            self.log_message('EXCEPTION - see syr.exception.log for details')
Beispiel #8
0
def add_contacts_crypto(contact, encryption_software, fingerprint=None, source=None):
    '''
        Add a contact's crypto record.

        >>> contacts_crypto = add_contacts_crypto(None, None)
        >>> contacts_crypto is None
        True
    '''
    if contact is None or encryption_software is None:
        contacts_crypto = None
    else:
        if fingerprint is None:
            formatted_fingerprint = None
        else:
            formatted_fingerprint = format_fingerprint(fingerprint)

        contacts_crypto = ContactsCrypto.objects.create(
                           contact=contact, encryption_software=encryption_software,
                           fingerprint=formatted_fingerprint, source=source)
        log_message("created contact crypto for {}: {}".format(contact, contacts_crypto is not None))

    return contacts_crypto
def notify_new_key_arrived(to_user, id_fingerprint_pairs):
    '''
        Notify user a new key arrived.

        >>> notify_new_key_arrived(None, None)
    '''

    if to_user is None or id_fingerprint_pairs is None or len(
            id_fingerprint_pairs) < 1:
        pass
    else:
        # use the first email address from the imported key
        try:
            email, __ = id_fingerprint_pairs[0]
        except:
            email = get_admin_email()

        header = i18n(
            "To be safe, verify their key now by following these instructions:"
        )
        tip = i18n("https://goodcrypto.com/qna/knowledge-base/user-verify-key")
        regular_notice = True
        if require_key_verified():
            regular_notice = False
            if is_metadata_address(email):
                domain = parse_domain(email)
                subject = i18n(
                    'Mail to {domain} cannot be sent until you verify the metadata key'
                    .format(domain=domain))
                body = i18n(
                    "You received a public key for the email address(es) below. No one can send mail to users with this domain until you verify the key and update the database if it's okay. Otherwise, any mail sent to {domain} will be returned to the sender."
                    .format(domain)),
            else:
                subject = i18n(
                    'Mail to {email} cannot be sent until you verify their key'
                    .format(email=email))
                body = i18n(
                    "You received a public key for the email address(es) below. You cannot send mail until you check with the sender to verify the key and update the database if it's okay. Otherwise, any mail you send to this user will be returned to you."
                ),
        else:
            if is_metadata_address(email):
                domain = parse_domain(email)
                subject = 'Metadata protection to {domain} is now ready'.format(
                    domain=domain)
                body = 'Unless you disable metadata protection, all mail to {domain} will now have both metadata and content encrypted.'.format(
                    domain=domain)
            else:
                subject = i18n(
                    'Mail to {email} is now private'.format(email=email))
                body = i18n(
                    "The content of all messages to {email} will be protected.  "
                    .format(email=email))
        body_text = "{}\n\n{} {}\n".format(body, header, tip)

        for (user_id, fingerprint) in id_fingerprint_pairs:
            body_text += "    {}: {}".format(user_id,
                                             format_fingerprint(fingerprint))

        if regular_notice:
            prefix = TAG_PREFIX
        else:
            prefix = TAG_WARNING

        notify_user(to_user, '{} - {}'.format(prefix, str(subject)), body_text)
def add_contact_records(email_or_fingerprint, crypto_name, user_initiated_search, job_id, queue_key):
    '''
        Add contact and associated crypto records in database.

        This function cannot be part of a class because it's
        passed to RQ which only accepts standalone functions, not
        functions in an instance of a class.  Also, the function must
        be defined before the class which calls it or located in a separate
        file and imported.

        Test extreme case.
        >>> add_contact_records(None, None, None, None, None)
        False
    '''
    result_ok = timed_out = False
    log_message('entered add_contact_records')

    try:
        __, email = parse_address(email_or_fingerprint)
        if email is None:
            key_id = email_or_fingerprint
        else:
            key_id = None

        log_message('adding a {} contact for {} if key retrieved by {} job'.format(
            crypto_name, email_or_fingerprint, job_id))
        key_plugin = KeyFactory.get_crypto(
          crypto_name, crypto_software.get_key_classname(crypto_name))

        if queue_key is None or job_id is None:
            result_ok = False
        else:
            MAX_WAIT = 10 * 60 # seconds

            queue = Queue.from_queue_key(queue_key, connection=key_plugin.get_queue_connection())
            job = queue.fetch_job(job_id)

            # if this function is added to a queue (RQ), then it never starts
            # so we're going to do this the old fashion way
            waited = 0
            while not job.is_finished and not job.is_failed and waited < MAX_WAIT:
                sleep(1)

            if job.is_failed:
                log_message('retrieving {} key for {} job failed'.format(crypto_name, email_or_fingerprint))
                result_ok = False
            else:
                # even if the job timed out, see if the key was retrieved
                result_ok, timed_out, output, error = key_plugin.get_background_job_results(
                   email_or_fingerprint, job)
                log_message("results from retrieving {} key for {}, result ok: {}; timed out: {}".format(
                    crypto_name, email_or_fingerprint, result_ok, timed_out))
                if result_ok:
                    imported_user_ids = key_plugin.parse_keyserver_ids_retrieved(error)
                    log_message("imported user ids: {}".format(imported_user_ids))
                    if len(imported_user_ids) < 1 and error:
                        log_message('error: {}'.format(error))
                if output: log_message('output: {}'.format(output))

        if result_ok:
            id_fingerprint_pairs = []
            for user_id, imported_key_id in imported_user_ids:
                contact = contacts.add(user_id, crypto_name, source=KEYSERVER)
                result_ok = contact is not None
                log_message("added contact's crypto for {}: {}".format(user_id, result_ok))

                if result_ok:
                    # change the outgoing policy if needed
                    if contact.outbound_encrypt_policy != DEFAULT_OUTBOUND_ENCRYPT_POLICY:
                        contact.outbound_encrypt_policy = DEFAULT_OUTBOUND_ENCRYPT_POLICY
                        contact.save()

                    # activate the contact's crypto "after save signal" to update the fingerprint
                    contacts_crypto = contacts.get_contacts_crypto(user_id, crypto_name)
                    if contacts_crypto is not None:
                        if contacts_crypto.fingerprint is None:
                            contacts_crypto.source = KEYSERVER
                            contacts_crypto.save()
                            if key_id is None:
                                fingerprint = imported_key_id
                            else:
                                fingerprint = key_id
                        else:
                            fingerprint = contacts_crypto.fingerprint
                    elif key_id is None:
                        fingerprint = imported_key_id
                    else:
                        fingerprint = key_id

                    id_fingerprint_pairs.append((contact.email, format_fingerprint(fingerprint)))
                else:
                    log_message('unable to add {} contact record for {}'.format(crypto_name, user_id))

            if result_ok and len(id_fingerprint_pairs) > 0:
                log_message('notifying {} about new keys: {}'.format(user_initiated_search, id_fingerprint_pairs))
                notify_new_key_arrived(user_initiated_search, id_fingerprint_pairs)

        elif timed_out:
            log_message('timed out retrieving a {} key for {}.'.format(
                crypto_name, email_or_fingerprint))
        else:
            log_message('unable to retrieve {} key for {}.'.format(
                crypto_name, email_or_fingerprint))

    except Exception as exception:
        record_exception()
        log_message('EXCEPTION - see syr.exception.log for details')
        result_ok = False

    log_message('ended add_contact_records: {}'.format(result_ok))

    return result_ok
Beispiel #11
0
def view_fingerprint(request):
    '''View the fingerprint for a user.'''

    if options.login_to_view_fingerprints() and not request.user.is_authenticated():
        context = {}
        context.update(csrf(request))
        response = redirect('/login/?next={}'.format(request.path), context)
    else:
        response = None
        form = forms.GetFingerprintForm()
        if request.method == 'POST':

            email = None
            encryption_software = None

            form = forms.GetFingerprintForm(request.POST)
            if form.is_valid():
                try:
                    email = form.cleaned_data['email']
                    encryption_software = form.cleaned_data['encryption_software']

                    page_title = i18n('{encryption_software} fingerprint for {email}'.format(
                        encryption_software=encryption_software, email=email))

                    fingerprint, verified, active = contacts.get_fingerprint(email, encryption_software.name)
                    if fingerprint is None:
                        fingerprint = i18n('No fingerprint defined')
                        checked = None
                    elif request.user.is_authenticated():
                        if verified:
                            checked = 'checked'
                        else:
                            checked = None
                        form_template = 'mail/verify_fingerprint.html'
                        response = render_to_response(
                            form_template, {'form': form,
                                            'page_title': page_title,
                                            'email': email,
                                            'encryption_name': encryption_software.name,
                                            'fingerprint': format_fingerprint(fingerprint),
                                            'checked': checked,
                                            'active': active,
                                            'requires': options.require_key_verified()},
                                            context_instance=RequestContext(request))

                    if response is None:
                        response = show_fingerprint(request, email, fingerprint, verified, active, page_title)
                except Exception:
                    record_exception()
                    log_message('EXCEPTION - see syr.exception.log for details')

            if response is None:
                log_message('view fingerprint post: {}'.format(request.POST))

        if response is None:
            form_template = 'mail/get_fingerprint.html'
            form = forms.GetFingerprintForm()
            response = render_to_response(
                form_template, {'form': form}, context_instance=RequestContext(request))

    return response
Beispiel #12
0
def add_contact_records(email_or_fingerprint, crypto_name,
                        user_initiated_search, job_id, queue_key):
    '''
        Add contact and associated crypto records in database.

        This function cannot be part of a class because it's
        passed to RQ which only accepts standalone functions, not
        functions in an instance of a class.  Also, the function must
        be defined before the class which calls it or located in a separate
        file and imported.

        Test extreme case.
        >>> add_contact_records(None, None, None, None, None)
        False
    '''
    result_ok = timed_out = False
    log_message('entered add_contact_records')

    try:
        __, email = parse_address(email_or_fingerprint)
        if email is None:
            key_id = email_or_fingerprint
        else:
            key_id = None

        log_message(
            'adding a {} contact for {} if key retrieved by {} job'.format(
                crypto_name, email_or_fingerprint, job_id))
        key_plugin = KeyFactory.get_crypto(
            crypto_name, crypto_software.get_key_classname(crypto_name))

        if queue_key is None or job_id is None:
            result_ok = False
        else:
            MAX_WAIT = 10 * 60  # seconds

            queue = Queue.from_queue_key(
                queue_key, connection=key_plugin.get_queue_connection())
            job = queue.fetch_job(job_id)

            # if this function is added to a queue (RQ), then it never starts
            # so we're going to do this the old fashion way
            waited = 0
            while not job.is_finished and not job.is_failed and waited < MAX_WAIT:
                sleep(1)

            if job.is_failed:
                log_message('retrieving {} key for {} job failed'.format(
                    crypto_name, email_or_fingerprint))
                result_ok = False
            else:
                # even if the job timed out, see if the key was retrieved
                result_ok, timed_out, output, error = key_plugin.get_background_job_results(
                    email_or_fingerprint, job)
                log_message(
                    "results from retrieving {} key for {}, result ok: {}; timed out: {}"
                    .format(crypto_name, email_or_fingerprint, result_ok,
                            timed_out))
                if result_ok:
                    imported_user_ids = key_plugin.parse_keyserver_ids_retrieved(
                        error)
                    log_message(
                        "imported user ids: {}".format(imported_user_ids))
                    if len(imported_user_ids) < 1 and error:
                        log_message('error: {}'.format(error))
                if output: log_message('output: {}'.format(output))

        if result_ok:
            id_fingerprint_pairs = []
            for user_id, imported_key_id in imported_user_ids:
                contact = contacts.add(user_id, crypto_name, source=KEYSERVER)
                result_ok = contact is not None
                log_message("added contact's crypto for {}: {}".format(
                    user_id, result_ok))

                if result_ok:
                    # change the outgoing policy if needed
                    if contact.outbound_encrypt_policy != DEFAULT_OUTBOUND_ENCRYPT_POLICY:
                        contact.outbound_encrypt_policy = DEFAULT_OUTBOUND_ENCRYPT_POLICY
                        contact.save()

                    # activate the contact's crypto "after save signal" to update the fingerprint
                    contacts_crypto = contacts.get_contacts_crypto(
                        user_id, crypto_name)
                    if contacts_crypto is not None:
                        if contacts_crypto.fingerprint is None:
                            contacts_crypto.source = KEYSERVER
                            contacts_crypto.save()
                            if key_id is None:
                                fingerprint = imported_key_id
                            else:
                                fingerprint = key_id
                        else:
                            fingerprint = contacts_crypto.fingerprint
                    elif key_id is None:
                        fingerprint = imported_key_id
                    else:
                        fingerprint = key_id

                    id_fingerprint_pairs.append(
                        (contact.email, format_fingerprint(fingerprint)))
                else:
                    log_message(
                        'unable to add {} contact record for {}'.format(
                            crypto_name, user_id))

            if result_ok and len(id_fingerprint_pairs) > 0:
                log_message('notifying {} about new keys: {}'.format(
                    user_initiated_search, id_fingerprint_pairs))
                notify_new_key_arrived(user_initiated_search,
                                       id_fingerprint_pairs)

        elif timed_out:
            log_message('timed out retrieving a {} key for {}.'.format(
                crypto_name, email_or_fingerprint))
        else:
            log_message('unable to retrieve {} key for {}.'.format(
                crypto_name, email_or_fingerprint))

    except Exception as exception:
        record_exception()
        log_message('EXCEPTION - see syr.exception.log for details')
        result_ok = False

    log_message('ended add_contact_records: {}'.format(result_ok))

    return result_ok
    def save(self):
        '''
            Save the fingerprint in the database.

            Test extreme case.
            >>> set_fingerprint_class = SetFingerprint(None)
            >>> set_fingerprint_class.save()
            False
        '''

        self.result_ok, self.crypto_name, self.email, self.key_plugin = prep_sync(
            self.contacts_encryption)
        if self.result_ok:
            try:
                # the contact's crypto record must exist or we'll get into an infinite loop
                # because whenever we add a contact's encryption for an email in our supported domain,
                # then this class is activated so we can complete the configuration
                if self.contacts_encryption is None:
                    self.result_ok = False
                    log_message('no contact encryption record for {}'.format(
                        self.email))
                else:
                    fingerprint, expiration_date = self.key_plugin.get_fingerprint(
                        self.email)
                    if fingerprint is None:
                        self.result_ok = False
                        log_message('no {} fingerprint found for {}'.format(
                            self.crypto_name, self.email))
                    else:
                        self.result_ok = True
                        try:
                            fingerprint = format_fingerprint(fingerprint)
                            if (self.contacts_encryption.fingerprint
                                    is not None
                                    and self.contacts_encryption.fingerprint !=
                                    fingerprint):
                                log_message(
                                    'replaced old fingerprint {} with {} for {}'
                                    .format(
                                        self.contacts_encryption.fingerprint,
                                        fingerprint, self.email))

                            # if we created the key, then be sure it's verified
                            if utils.email_in_domain(self.email):
                                if self.contacts_encryption.source is None and create_private_keys(
                                ):
                                    self.contacts_encryption.source = AUTO_GENERATED
                                if self.contacts_encryption.source == AUTO_GENERATED:
                                    self.contacts_encryption.verified = True

                            self.contacts_encryption.fingerprint = fingerprint
                            self.contacts_encryption.save()
                            log_message(
                                'set {} fingerprint for {} in database: {}'.
                                format(self.crypto_name, self.email,
                                       fingerprint))
                        except IntegrityError as ie:
                            self.result_ok = False
                            if 'insert or update on table "mail_contactscrypto" violates foreign key constraint' in str(
                                    ie):
                                log_message(
                                    '{} crypto key no longer exists for {}'.
                                    format(self.crypto_name, self.email))
                            else:
                                raise
            except Exception as exception:
                record_exception()
                log_message('EXCEPTION - see syr.exception.log for details')
                self.result_ok = False

        return self.result_ok
Beispiel #14
0
def add(email, encryption_program, fingerprint=None, passcode=None, source=None):
    '''
        Add a contact and related settings.

        >>> # In honor of Thomas Drake, a whistleblower about Trailblazer, a NSA mass surveillance project.
        >>> email = '*****@*****.**'
        >>> encryption_software = crypto_software.get(KeyFactory.DEFAULT_ENCRYPTION_NAME)
        >>> contact = add(email, KeyFactory.DEFAULT_ENCRYPTION_NAME)
        >>> contact.email
        '*****@*****.**'
        >>> contact.user_name
        'Thomas'
        >>> address = contact.email
        >>> address = '*****@*****.**'
        >>> contacts_crypto = ContactsCrypto.objects.get(
        ...    contact=contact, encryption_software=encryption_software)
        >>> contacts_crypto is not None
        True
        >>> x = contact.delete()
        >>> contact = add(None, encryption_software)
        >>> contact is None
        True
        >>> contact = add(email, None)
        >>> contact.email = '*****@*****.**'
        >>> contact.user_name = 'Thomas'
        >>> get_contacts_crypto(email)
        []
        >>> x = contact.delete()
        >>> contact = add(None, None)
        >>> contact is None
        True
        >>> contact = add('*****@*****.**', None)
        >>> contact.email = '*****@*****.**'
        >>> contact.user_name = 'test.com domain key (system use only)'
        >>> x = contact.delete()
    '''

    try:
        new_contact = True
        user_name, email_address = parse_address(email)
        if email_address is None:
            contact = None
        else:
            try:
                contact = Contact.objects.get(email=email_address)
                new_contact = False

                # update the user name if it's been given and it differs from the name in the DB
                if user_name is not None and contact.user_name != user_name:
                    contact.user_name = user_name
                    contact.save()
                    log_message('updated {} user name to {}'.format(email_address, user_name))
            except Contact.DoesNotExist:
                log_message('creating a contact for {}'.format(email_address))
                try:
                    if user_name is None or len(user_name.strip()) <= 0:
                        from goodcrypto.mail.message.metadata import is_metadata_address

                        user_name = email_address
                        i = user_name.find('@')

                        # handle domain keys specially
                        if is_metadata_address(email_address):
                            if i > 0:
                                email_domain = user_name[i+1:]
                            user_name = '{} domain key (system use only)'.format(email_domain)
                        else:
                            if i > 0:
                                user_name = user_name[:i]
                            user_name = user_name.replace('.', ' ').replace('-', ' ').replace('_', ' ')
                            user_name = capwords(user_name)
                except:
                    pass

                contact = Contact.objects.create(email=email_address, user_name=user_name)
            except Exception:
                record_exception()
                log_message('EXCEPTION - see syr.exception.log for details')
                contact = None

        if encryption_program is None:
            log_message("no encryption software defined so not creating contact's crytpo record for {}".format(email))
        else:
            # add a corresponding record for the contact's crypto program
            encryption_software = crypto_software.get(encryption_program)
            if contact is None or encryption_software is None:
                log_message('no contact and/or encryption software defined')
            else:
                try:
                    contacts_crypto = ContactsCrypto.objects.get(
                      contact=contact, encryption_software=encryption_software)
                    if (fingerprint is not None and
                        strip_fingerprint(contacts_crypto.fingerprint) != strip_fingerprint(fingerprint)):
                        contacts_crypto.fingerprint = format_fingerprint(fingerprint)
                        if email_in_domain(email):
                            if contacts.crypto.source is None:
                                contacts.crypto.source = constants.AUTO_GENERATED
                            if contacts_crypto.source == constants.AUTO_GENERATED:
                                contacts_crypto.verified = True
                        contacts_crypto.save()
                except ContactsCrypto.DoesNotExist:
                    # if the contact existed without any contact crypto, but was set
                    # to never encrypt and now we have a key, then change the
                    # outbound encrypt policy to the default
                    if (not new_contact and
                        contact.outbound_encrypt_policy == constants.NEVER_ENCRYPT_OUTBOUND):
                        contact.outbound_encrypt_policy = constants.DEFAULT_OUTBOUND_ENCRYPT_POLICY
                        contact.save()

                    contacts_crypto = add_contacts_crypto(contact, encryption_software,
                        fingerprint=fingerprint, source=source)

                    log_message("created {} crypto record for {} with {} fingerprint: {}".format(
                        encryption_software, email, fingerprint, contacts_crypto is not None))
                except:
                    record_exception()
                    log_message('EXCEPTION - see syr.exception.log for details')

    except Exception:
        contact = None
        record_exception()
        log_message('EXCEPTION - see syr.exception.log for details')

    return contact
Beispiel #15
0
    def take_api_action(self):

        result = None

        ok, error_message = self.is_data_ok()
        if ok:
            if self.action == api_constants.CONFIGURE:
                mail_options = options.get_options()
                mail_options.domain = self.domain
                mail_options.mail_server_address = self.mail_server_address
                options.save_options(mail_options)
                result = self.format_result(api_constants.CONFIGURE, ok)
                self.log_message('configure result: {}'.format(result))

            elif self.action == api_constants.CREATE_SUPERUSER:
                user, password, error_message = create_superuser(self.admin)
                if error_message is None:
                    if password is None:
                        result = self.format_bad_result(error_message)
                    else:
                        result = self.format_message_result(
                            api_constants.CREATE_SUPERUSER, ok, password)
                else:
                    result = self.format_bad_result(error_message)
                self.log_message('create user result: {}'.format(result))

            elif self.action == api_constants.STATUS:
                result = self.format_result(api_constants.STATUS,
                                            get_mail_status())
                self.log_message('status result: {}'.format(result))

            elif self.action == api_constants.IMPORT_KEY:
                from goodcrypto.mail.import_key import import_key_now

                result_ok, status, fingerprint_ok = import_key_now(
                    self.encryption_name, self.public_key, self.user_name,
                    self.fingerprint, self.password)
                if result_ok:
                    __, email = status.split(':')
                    result = self.format_message_result(
                        api_constants.IMPORT_KEY, True, email)
                else:
                    result = self.format_bad_result(status)
                self.log_message('import key result: {}'.format(result))

            elif self.action == api_constants.GET_CONTACT_LIST:

                email_addresses = contacts.get_contact_list(
                    self.encryption_name)
                addresses = '\n'.join(email_addresses)
                result = self.format_message_result(
                    api_constants.GET_CONTACT_LIST, True, addresses)
                self.log_message('{} {} contacts found'.format(
                    len(email_addresses), self.encryption_name))

            elif self.action == api_constants.GET_FINGERPRINT:

                fingerprint, verified, __ = contacts.get_fingerprint(
                    self.email, self.encryption_name)
                if fingerprint is None:
                    ok = False
                    error_message = 'No {} fingerprint for {}'.format(
                        self.encryption_name, self.email)
                    result = self.format_bad_result(error_message)
                    self.log_message('bad result: {}'.format(result))
                else:
                    message = 'Fingerprint: {} verified: {}'.format(
                        format_fingerprint(fingerprint), verified)
                    result = self.format_message_result(
                        api_constants.GET_FINGERPRINT, True, message)
                    self.log_message(message)

            else:
                ok = False
                error_message = 'Bad action: {}'.format(self.action)
                result = self.format_bad_result(error_message)
                self.log_message('bad action result: {}'.format(result))

        else:
            result = self.format_bad_result(error_message)
            self.log_message('data is bad')

        return result
Beispiel #16
0
    def take_api_action(self):

        result = None

        ok, error_message = self.is_data_ok()
        if ok:
            if self.action == api_constants.CONFIGURE:
                mail_options = options.get_options()
                mail_options.domain = self.domain
                mail_options.mail_server_address = self.mail_server_address
                options.save_options(mail_options)
                result = self.format_result(api_constants.CONFIGURE, ok)
                self.log_message('configure result: {}'.format(result))

            elif self.action == api_constants.CREATE_SUPERUSER:
                user, password, error_message = create_superuser(self.admin)
                if error_message is None:
                    if password is None:
                        result = self.format_bad_result(error_message)
                    else:
                        result = self.format_message_result(api_constants.CREATE_SUPERUSER, ok, password)
                else:
                    result = self.format_bad_result(error_message)
                self.log_message('create user result: {}'.format(result))

            elif self.action == api_constants.STATUS:
                result = self.format_result(api_constants.STATUS, get_mail_status())
                self.log_message('status result: {}'.format(result))

            elif self.action == api_constants.IMPORT_KEY:
                from goodcrypto.mail.import_key import import_key_now

                result_ok, status, fingerprint_ok = import_key_now(
                    self.encryption_name, self.public_key, self.user_name, self.fingerprint, self.password)
                if result_ok:
                    __, email = status.split(':')
                    result = self.format_message_result(api_constants.IMPORT_KEY, True, email)
                else:
                    result = self.format_bad_result(status)
                self.log_message('import key result: {}'.format(result))

            elif self.action == api_constants.GET_CONTACT_LIST:

                email_addresses = contacts.get_contact_list(self.encryption_name)
                addresses = '\n'.join(email_addresses)
                result = self.format_message_result(api_constants.GET_CONTACT_LIST, True, addresses)
                self.log_message('{} {} contacts found'.format(len(email_addresses), self.encryption_name))

            elif self.action == api_constants.GET_FINGERPRINT:

                fingerprint, verified, __ = contacts.get_fingerprint(self.email, self.encryption_name)
                if fingerprint is None:
                    ok = False
                    error_message = 'No {} fingerprint for {}'.format(self.encryption_name, self.email)
                    result = self.format_bad_result(error_message)
                    self.log_message('bad result: {}'.format(result))
                else:
                    message = 'Fingerprint: {} verified: {}'.format(format_fingerprint(fingerprint), verified)
                    result = self.format_message_result(api_constants.GET_FINGERPRINT, True, message)
                    self.log_message(message)

            else:
                ok = False
                error_message = 'Bad action: {}'.format(self.action)
                result = self.format_bad_result(error_message)
                self.log_message('bad action result: {}'.format(result))

        else:
            result = self.format_bad_result(error_message)
            self.log_message('data is bad')

        return result
def add(email,
        encryption_program,
        fingerprint=None,
        passcode=None,
        source=None):
    '''
        Add a contact and related settings.

        >>> # In honor of Thomas Drake, a whistleblower about Trailblazer, a NSA mass surveillance project.
        >>> email = '*****@*****.**'
        >>> encryption_software = crypto_software.get(KeyFactory.DEFAULT_ENCRYPTION_NAME)
        >>> contact = add(email, KeyFactory.DEFAULT_ENCRYPTION_NAME)
        >>> contact.email
        '*****@*****.**'
        >>> contact.user_name
        'Thomas'
        >>> address = contact.email
        >>> address = '*****@*****.**'
        >>> contacts_crypto = ContactsCrypto.objects.get(
        ...    contact=contact, encryption_software=encryption_software)
        >>> contacts_crypto is not None
        True
        >>> x = contact.delete()
        >>> contact = add(None, encryption_software)
        >>> contact is None
        True
        >>> contact = add(email, None)
        >>> contact.email = '*****@*****.**'
        >>> contact.user_name = 'Thomas'
        >>> get_contacts_crypto(email)
        []
        >>> x = contact.delete()
        >>> contact = add(None, None)
        >>> contact is None
        True
        >>> contact = add('*****@*****.**', None)
        >>> contact.email = '*****@*****.**'
        >>> contact.user_name = 'test.com domain key (system use only)'
        >>> x = contact.delete()
    '''

    try:
        new_contact = True
        user_name, email_address = parse_address(email)
        if email_address is None:
            contact = None
        else:
            try:
                contact = Contact.objects.get(email=email_address)
                new_contact = False

                # update the user name if it's been given and it differs from the name in the DB
                if user_name is not None and contact.user_name != user_name:
                    contact.user_name = user_name
                    contact.save()
                    log_message('updated {} user name to {}'.format(
                        email_address, user_name))
            except Contact.DoesNotExist:
                log_message('creating a contact for {}'.format(email_address))
                try:
                    if user_name is None or len(user_name.strip()) <= 0:
                        from goodcrypto.mail.message.metadata import is_metadata_address

                        user_name = email_address
                        i = user_name.find('@')

                        # handle domain keys specially
                        if is_metadata_address(email_address):
                            if i > 0:
                                email_domain = user_name[i + 1:]
                            user_name = '{} domain key (system use only)'.format(
                                email_domain)
                        else:
                            if i > 0:
                                user_name = user_name[:i]
                            user_name = user_name.replace('.', ' ').replace(
                                '-', ' ').replace('_', ' ')
                            user_name = capwords(user_name)
                except:
                    pass

                contact = Contact.objects.create(email=email_address,
                                                 user_name=user_name)
            except Exception:
                record_exception()
                log_message('EXCEPTION - see syr.exception.log for details')
                contact = None

        if encryption_program is None:
            log_message(
                "no encryption software defined so not creating contact's crytpo record for {}"
                .format(email))
        else:
            # add a corresponding record for the contact's crypto program
            encryption_software = crypto_software.get(encryption_program)
            if contact is None or encryption_software is None:
                log_message('no contact and/or encryption software defined')
            else:
                try:
                    contacts_crypto = ContactsCrypto.objects.get(
                        contact=contact,
                        encryption_software=encryption_software)
                    if (fingerprint is not None
                            and strip_fingerprint(contacts_crypto.fingerprint)
                            != strip_fingerprint(fingerprint)):
                        contacts_crypto.fingerprint = format_fingerprint(
                            fingerprint)
                        if email_in_domain(email):
                            if contacts.crypto.source is None:
                                contacts.crypto.source = constants.AUTO_GENERATED
                            if contacts_crypto.source == constants.AUTO_GENERATED:
                                contacts_crypto.verified = True
                        contacts_crypto.save()
                except ContactsCrypto.DoesNotExist:
                    # if the contact existed without any contact crypto, but was set
                    # to never encrypt and now we have a key, then change the
                    # outbound encrypt policy to the default
                    if (not new_contact and contact.outbound_encrypt_policy
                            == constants.NEVER_ENCRYPT_OUTBOUND):
                        contact.outbound_encrypt_policy = constants.DEFAULT_OUTBOUND_ENCRYPT_POLICY
                        contact.save()

                    contacts_crypto = add_contacts_crypto(
                        contact,
                        encryption_software,
                        fingerprint=fingerprint,
                        source=source)

                    log_message(
                        "created {} crypto record for {} with {} fingerprint: {}"
                        .format(encryption_software, email, fingerprint,
                                contacts_crypto is not None))
                except:
                    record_exception()
                    log_message(
                        'EXCEPTION - see syr.exception.log for details')

    except Exception:
        contact = None
        record_exception()
        log_message('EXCEPTION - see syr.exception.log for details')

    return contact