Пример #1
0
def get_admin_email():
    '''
        Get the admin's email.

        >>> email = get_admin_email()
        >>> email is not None
        True
        >>> email.endswith(get_domain())
        True
    '''

    admin_email = None
    try:
        users = User.objects.filter(is_superuser=True)
        if users is not None and len(users) > 0:
            for user in users:
                email = user.email
                if email is not None and len(email.strip()) > 0:
                    admin_email = email
                    break
                else:
                    username = user.username
                    email = get_email(user.username)
                    if email is not None and len(email.strip()) > 0:
                        admin_email = email
                        break
    except:
        record_exception()
        log_message('EXCEPTION - see syr.exception.log for details')

    if admin_email is None:
        admin_email = 'daemon@{}'.format(get_domain())

    return admin_email
Пример #2
0
    def prep_message_header(self, message, to_domain):
        ''' Prepare the header of a Message. '''

        if message is None:
            self.log_message('no message defined in prep_message_header')
        elif to_domain is None:
            self.log_message('domain is not defined in prep_message_header')
        else:
            message_date = datetime.utcnow().replace(tzinfo=utc)
            from_user = get_metadata_address(domain=get_domain())
            to_user = get_metadata_address(domain=to_domain)

            message.__setitem__(mime_constants.FROM_KEYWORD, from_user)
            message.__setitem__(mime_constants.TO_KEYWORD, to_user)
            message.__setitem__(constants.ORIGINAL_FROM, from_user)
            message.__setitem__(constants.ORIGINAL_TO, to_user)
            message.__setitem__(mime_constants.DATE_KEYWORD,
                                message_date.__str__())
            message.__setitem__(mime_constants.MESSAGE_ID_KEYWORD,
                                utils.get_message_id())
            self.log_message("message's content type: {}".format(
                message.get_content_type()))
            self.log_message("message's boundary: {}".format(
                message.get_boundary()))
            if self.DEBUGGING:
                self.log_message("message's key/value pair")
                for key in message.keys():
                    self.log_message('{}: {}'.format(key, message.get(key)))

        return message
Пример #3
0
def get_mail_status():
    '''
        Return whether Mail is running.

        >>> status = get_mail_status()
        >>> status == 'green'
        True
    '''

    programs_running = is_mail_running()
    domain = get_domain()
    mta = mail_server_address()
    app_configured = (domain is not None and len(domain.strip()) > 0 and
                      mta is not None and len(mta.strip()) > 0)

    if programs_running:
        if app_configured:
            status = STATUS_GREEN
        else:
            status = STATUS_YELLOW
    else:
        status = STATUS_RED

    if status != STATUS_GREEN:
        log_message('is postfix running: {}'.format(is_program_running('postfix/master')))
        log_message('is rqworker running: {}'.format(is_program_running('rqworker')))
        log_message('is redis running: {}'.format(is_program_running('redis')))
        log_message('programs running: {}'.format(programs_running))
        log_message('domain ok: {}'.format(domain is not None and len(domain.strip()) > 0))
        log_message('mta ok: {}'.format(mta is not None and len(mta.strip()) > 0))
        log_message('app_configured: {}'.format(app_configured))

    return status
Пример #4
0
    def create_encrypted_message(self, inner_message, to_domain):
        ''' Create an encrypted Message. '''

        message = None

        if to_domain is None:
            self.log_message('domain is not defined')
        elif inner_message is None:
            self.log_message('no inner message defined')
        else:
            from_user = get_email(get_metadata_address(domain=get_domain()))
            to_user = get_email(get_metadata_address(domain=to_domain))

            crypto_message = create_protected_message(
                from_user, to_user, inner_message.as_string(),
                utils.get_message_id())
            if crypto_message.is_crypted():

                # add the DKIM signature to the inner message if user opted for it
                crypto_message = add_dkim_sig_optionally(crypto_message)

                message = crypto_message.get_email_message().get_message()
                self.crypted_with = crypto_message.get_metadata_crypted_with()
                self.log_message('crypted with: {}'.format(self.crypted_with))
                for part in message.walk():
                    self.log_message('Content type of part: {}'.format(
                        part.get_content_type()))
                    if self.DEBUGGING: self.log_message(part.get_payload())
            else:
                report_bad_bundled_encrypted_message(to_domain,
                                                     self.bundled_messages)

        return message
def add_dkim_sig_optionally(crypto_message):
    ''' Add DKIM signature if option selected. '''

    if (options.add_dkim_sig() and options.dkim_public_key() is not None
            and len(options.dkim_public_key()) > 0):

        log_message('trying to add DKIM signature')

        try:
            global log

            SELECTOR = b'mail'
            DKIM_SIG = b'DKIM-Signature'
            PRIVATE_KEY_FILE = '/etc/opendkim/{}/dkim.private.key'.format(
                get_domain())

            # in case there's a mixture of CR-LF and LF lines, convert CR-LF to LF and then all LFs to CR-LFs
            message = crypto_message.get_email_message().to_string().replace(
                constants.CRLF, constants.LF).replace(constants.LF,
                                                      constants.CRLF)

            charset, __ = get_charset(crypto_message.get_email_message())
            msg = bytes(message, charset)
            with open(PRIVATE_KEY_FILE, 'rb') as f:
                private_key = f.read()

            dkim = DKIM(message=msg, minkey=constants.MIN_DKIM_KEY, logger=log)
            # stop header injections of standard headers
            dkim.frozen_sign = set(DKIM.RFC5322_SINGLETON)
            sig = dkim.sign(SELECTOR, get_domain().encode(), private_key)
            if sig.startswith(DKIM_SIG):
                signed_message = '{}{}'.format(sig.decode(), message)
                crypto_message.get_email_message().set_message(signed_message)
                crypto_message.set_dkim_signed(True)
                crypto_message.set_dkim_sig_verified(True)
                log_message('added DKIM signature successfully')
            else:
                log_message('error trying to add DKIM signature')
        except ParameterError as pe:
            log_message(str(pe))
        except:
            log_message('EXCEPTION - see syr.exception.log for details')
            record_exception()

    return crypto_message
Пример #6
0
def add_dkim_sig_optionally(crypto_message):
    ''' Add DKIM signature if option selected. '''

    if (options.add_dkim_sig() and
        options.dkim_public_key() is not None and
        len(options.dkim_public_key()) > 0):

        log_message('trying to add DKIM signature')

        try:
            global log

            SELECTOR = b'mail'
            DKIM_SIG = b'DKIM-Signature'
            PRIVATE_KEY_FILE = '/etc/opendkim/{}/dkim.private.key'.format(get_domain())

            # in case there's a mixture of CR-LF and LF lines, convert CR-LF to LF and then all LFs to CR-LFs
            message = crypto_message.get_email_message().to_string().replace(
                constants.CRLF, constants.LF).replace(constants.LF, constants.CRLF)

            charset, __ = get_charset(crypto_message.get_email_message())
            msg = bytes(message, charset)
            with open(PRIVATE_KEY_FILE, 'rb') as f:
                private_key = f.read()

            dkim = DKIM(message=msg, minkey=constants.MIN_DKIM_KEY, logger=log)
            # stop header injections of standard headers
            dkim.frozen_sign = set(DKIM.RFC5322_SINGLETON)
            sig = dkim.sign(SELECTOR, get_domain().encode(), private_key)
            if sig.startswith(DKIM_SIG):
                signed_message = '{}{}'.format(sig.decode(), message)
                crypto_message.get_email_message().set_message(signed_message)
                crypto_message.set_dkim_signed(True)
                crypto_message.set_dkim_sig_verified(True)
                log_message('added DKIM signature successfully')
            else:
                log_message('error trying to add DKIM signature')
        except ParameterError as pe:
            log_message(str(pe))
        except:
            log_message('EXCEPTION - see syr.exception.log for details')
            record_exception()

    return crypto_message
Пример #7
0
def get_domain_email():
    '''
        Get the email address for a domain key.

        >>> domain = get_domain_email()
        >>> domain == '*****@*****.**'
        True
    '''

    return '{}@{}'.format(get_domain_user(), get_domain())
Пример #8
0
def get_message_id():
    ''' Get a unique message id. '''

    Chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-.'

    random_chars = ''
    for i in range(10):
        random_chars += choice(Chars)

    timestamp = time.strftime('%Y%m%d%H%M%S', time.gmtime())
    message_id = '{}{}@{}'.format(random_chars, timestamp, get_domain())

    return message_id
Пример #9
0
def report_metadata_key_creation_error(email):
    '''
        Report that an error occurred creating a metadata key.

        >>> report_metadata_key_creation_error('*****@*****.**')
    '''

    subject = i18n('GoodCrypto - Error while creating a private metadata key')
    body = '{}.\n{}'.format(
        subject,
       i18n("Metadata cannot be protected until you create a private key for {}@{}".format(
           DOMAIN_USER, get_domain())))
    notify_user(email, subject, body)
Пример #10
0
def report_metadata_key_creation_error(email):
    '''
        Report that an error occurred creating a metadata key.

        >>> report_metadata_key_creation_error('*****@*****.**')
    '''

    subject = i18n('GoodCrypto - Error while creating a private metadata key')
    body = '{}.\n{}'.format(
        subject,
        i18n(
            "Metadata cannot be protected until you create a private key for {}@{}"
            .format(DOMAIN_USER, get_domain())))
    notify_user(email, subject, body)
Пример #11
0
    def clean(self):
        '''Verify there is only 1 general info record.'''

        cleaned_data = super(OptionsAdminForm, self).clean()

        # the mail_server_address should either be an ip address or a domain
        mail_server_address = cleaned_data.get('mail_server_address')
        if is_mta_ok(mail_server_address):
            _log.write('mail server address ok')
            self.cleaned_data['mail_server_address'] = mail_server_address
        else:
            del self.cleaned_data['mail_server_address']
            _log.write('deleted mail server address from cleaned data')

            if mail_server_address is None or len(
                    mail_server_address.strip()) <= 0:
                error_message = i18n(
                    'You need to define the mail server address (MTA).')
            else:
                error_message = i18n(
                    'The mail server address contains one or more bad characters or spaces.'
                )
            _log.write(error_message)

            raise forms.ValidationError(error_message, code='invalid')

        encrypt_metadata = cleaned_data.get('encrypt_metadata')
        bundle_and_pad = cleaned_data.get('bundle_and_pad')
        if bundle_and_pad and not encrypt_metadata:
            del self.cleaned_data['encrypt_metadata']
            _log.write('deleted encrypt_metadata from cleaned data')
            del self.cleaned_data['bundle_and_pad']
            _log.write('deleted bundle_and_pad from cleaned data')

            error_message = i18n(
                'You can only bundle and pad messages if you also encrypt metadata. Either add a check mark to "Encrypt metadata" or remove the check mark from "Bundle and pad".'
            )
            _log.write(error_message)

            raise forms.ValidationError(error_message, code='invalid')

        add_dkim_sig = cleaned_data.get('add_dkim_sig')
        dkim_public_key = cleaned_data.get('dkim_public_key')
        if add_dkim_sig:
            if not dkim_public_key or len(dkim_public_key.strip()) <= 0:
                config_dkim.start(get_domain())
                _log.write('starting to configure dkim')

        return cleaned_data
Пример #12
0
def add_private_key(email, encryption_software=None):
    '''
        Add a private key if it doesn't exist.

        Creating a key takes minutes so a separate process handles it so no return code.

        >>> add_private_key(None)
    '''

    try:
        # only add private keys for members of the domain
        if email_in_domain(email):
            if options.create_private_keys():
                if encryption_software is None or len(encryption_software) <= 0:
                    encryption_software = CryptoFactory.DEFAULT_ENCRYPTION_NAME

                user_key = user_keys.get(email, encryption_software)
                if user_key is None:
                    contacts_crypto = contacts.get_contacts_crypto(email, encryption_name=encryption_software)
                    if contacts_crypto is None:
                        # a private user key will automatically be created
                        # when the contact's crypto record is created after the contact is created
                        contacts.add(email, encryption_software, source=AUTO_GENERATED)
                        log_message('add {} key for {}'.format(encryption_software, email))
                    else:
                        log_message('adding private {} user key for {}'.format(encryption_software, email))
                        sync_private_key_via_queue(contacts_crypto)

                elif user_key.contacts_encryption.fingerprint is None:
                    log_message('setting private {} key fingerprint for {}'.format(encryption_software, email))
                    sync_fingerprint_via_queue(user_key.contacts_encryption)
                else:
                    log_message('{} already has crypto software defined'.format(email))
            else:
                log_message('creating private key disabled so no key created for {}'.format(email))
        else:
            log_message('{} not a member of {}'.format(email, get_domain()))

    except Exception:
        record_exception()
        log_message('EXCEPTION - see syr.exception.log for details')
Пример #13
0
def main(argv):
    # set the defaults
    crypto_name = CryptoFactory.DEFAULT_ENCRYPTION_NAME

    # use the args passed on the command line
    if argv and len(argv) >= 1:
        pathname = argv[0]
        if len(argv) >= 2:
            crypto_name = argv[1]

        crypto = crypto_software.get(crypto_name)
        if crypto is None:
            print('{} encryption not defined in database'.format(crypto_name))
        else:
            domain = get_domain()
            with open(pathname, 'rt') as f:
                lines = f.readlines()
                for line in lines:
                    if len(line.strip()) > 0 and not line.startswith('#'):
                        make_key(line, domain, crypto_name)
    else:
        print_usage()
def main(argv):
    # set the defaults
    crypto_name = CryptoFactory.DEFAULT_ENCRYPTION_NAME

    # use the args passed on the command line
    if argv and len(argv) >= 1:
        pathname = argv[0]
        if len(argv) >= 2:
            crypto_name = argv[1]

        crypto = crypto_software.get(crypto_name)
        if crypto is None:
            print('{} encryption not defined in database'.format(crypto_name))
        else:
            domain = get_domain()
            with open(pathname, 'rt') as f:
                lines = f.readlines()
                for line in lines:
                    if len(line.strip()) > 0 and not line.startswith('#'):
                        make_key(line, domain, crypto_name)
    else:
        print_usage()
Пример #15
0
    def send_bundled_message(self, message, to_domain):
        ''' Send a Message to the domain. '''

        try:
            if message is None:
                result_ok = False
                self.log_message('nothing to send to {}'.format(to_domain))
            else:
                sender = get_email(get_metadata_address(domain=get_domain()))
                recipient = get_email(get_metadata_address(domain=to_domain))
                self.log_message(
                    'starting to send message from {} to {}'.format(
                        sender, recipient))
                result_ok = send_message(sender, recipient,
                                         message.as_string())
                self.log_message('finished sending message')
        except Exception as exception:
            result_ok = False
            self.log_message('error while sending message')
            self.log_message('EXCEPTION - see syr.exception.log for details')
            record_exception()

        return result_ok
Пример #16
0
def email_in_domain(email):
    ''' Determine if the email address has the supported domain.

        >>> # In honor of Sergeant First Class Amitai, who co-signed letter and refused to serve
        >>> # in operations involving the occupied Palestinian territories because
        >>> # of the widespread surveillance of innocent residents.
        >>> email_in_domain('*****@*****.**')
        True
        >>> email_in_domain('*****@*****.**')
        False
    '''
    if email is None:
        result_ok = False
    else:
        domain = get_domain()
        address = get_email(email)

        if address is None  or len(address) <= 0 or domain is None or len(domain) <= 0:
            result_ok = False
        else:
            result_ok = address.lower().endswith('@{}'.format(domain.lower()))

    return result_ok
Пример #17
0
def home(request):
    '''Show the home page.'''

    domain = get_domain()
    if domain is None or len(domain.strip()) <= 0:
        log_message('redirecting to system configuration')
        response = HttpResponseRedirect('/system/customize/')
    else:
        is_secure = is_secure_connection(request)
        params = {
            'domain': domain,
            'secure': is_secure,
            'fingerprint_login_req': options.login_to_view_fingerprints(),
            'export_login_req': options.login_to_export_keys(),
            'use_keyservers': options.use_keyservers()
        }
        mta = options.mail_server_address()
        if mta is not None and len(mta.strip()) > 0:
            params['mta'] = mta

        template = 'mail/home.html'
        response = render_to_response(template, params, context_instance=RequestContext(request))

    return response
Пример #18
0
def main(argv):
    # set the defaults
    crypto_name = CryptoFactory.DEFAULT_ENCRYPTION_NAME
    parent_dir = '/var/local/projects/goodcrypto/server/data/oce/pubkeys'

    # use the args passed on the command line
    if argv and len(argv) >= 1:
        parent_dir = argv[0]
        if len(argv) >= 2:
            crypto_name = argv[1]

    if not os.path.exists(parent_dir):
        os.makedirs(parent_dir)

    domain = get_domain()

    gpg_crypto = crypto_software.get(crypto_name)
    contacts = Contact.objects.filter(email__iendswith=domain)
    for contact in contacts:
        email = contact.email
        public_key = get_public_key(email, gpg_crypto)
        filename = os.path.join(parent_dir, email + '.asc')
        with open(filename, 'wt') as f:
            f.write(public_key)
def main(argv):
    # set the defaults
    crypto_name = CryptoFactory.DEFAULT_ENCRYPTION_NAME
    parent_dir = '/var/local/projects/goodcrypto/server/data/oce/pubkeys'

    # use the args passed on the command line
    if argv and len(argv) >= 1:
        parent_dir = argv[0]
        if len(argv) >= 2:
            crypto_name = argv[1]

    if not os.path.exists(parent_dir):
        os.makedirs(parent_dir)

    domain = get_domain()

    gpg_crypto = crypto_software.get(crypto_name)
    contacts = Contact.objects.filter(email__iendswith=domain)
    for contact in contacts:
        email = contact.email
        public_key = get_public_key(email, gpg_crypto)
        filename = os.path.join(parent_dir, email + '.asc')
        with open(filename, 'wt') as f:
            f.write(public_key)
Пример #20
0
from goodcrypto.mail.message.metadata import is_metadata_address
from goodcrypto.mail.options import goodcrypto_server_url, require_key_verified
from goodcrypto.mail.utils import get_admin_email, parse_domain, send_message, write_message
from goodcrypto.mail.utils.dirs import get_notices_directory
from goodcrypto.oce.utils import format_fingerprint
from goodcrypto.utils import get_email, i18n
from goodcrypto.utils.log_file import LogFile
from syr.exception import record_exception
from syr.message import prep_mime_message


USE_SMTP = False

#  Notices From: address.
NOTICE_FROM_NAME = 'GoodCrypto Private Server Daemon'
NOTICE_FROM_EMAIL = 'mailer-daemon@{}'.format(get_domain())
NOTICE_FROM_ADDRESS = (NOTICE_FROM_NAME, NOTICE_FROM_EMAIL)
NOTICE_FROM_ADDR = formataddr(NOTICE_FROM_ADDRESS)

# shared details
CREDENTIALS_SUBJECT = i18n('GoodCrypto - Save these credentials')
VERIFY_HEADER = i18n('To verify a message was received privately:')

_log = None


def send_user_credentials(email, password):
    '''
        Email the user with their credentials to access private website.

        >>> send_user_credentials('*****@*****.**', 'test-password')
Пример #21
0
from goodcrypto.mail.message.inspect_utils import get_hashcode
from goodcrypto.mail.message.metadata import is_metadata_address
from goodcrypto.mail.options import goodcrypto_server_url, require_key_verified
from goodcrypto.mail.utils import get_admin_email, parse_domain, send_message, write_message
from goodcrypto.mail.utils.dirs import get_notices_directory
from goodcrypto.oce.utils import format_fingerprint
from goodcrypto.utils import get_email, i18n
from goodcrypto.utils.log_file import LogFile
from syr.exception import record_exception
from syr.message import prep_mime_message

USE_SMTP = False

#  Notices From: address.
NOTICE_FROM_NAME = 'GoodCrypto Private Server Daemon'
NOTICE_FROM_EMAIL = 'mailer-daemon@{}'.format(get_domain())
NOTICE_FROM_ADDRESS = (NOTICE_FROM_NAME, NOTICE_FROM_EMAIL)
NOTICE_FROM_ADDR = formataddr(NOTICE_FROM_ADDRESS)

# shared details
CREDENTIALS_SUBJECT = i18n('GoodCrypto - Save these credentials')
VERIFY_HEADER = i18n('To verify a message was received privately:')

_log = None


def send_user_credentials(email, password):
    '''
        Email the user with their credentials to access private website.

        >>> send_user_credentials('*****@*****.**', 'test-password')