コード例 #1
0
ファイル: authentication.py プロジェクト: hevelius/GlobaLeaks
    def post(self):
        request = self.validate_message(self.request.content.read(), requests.AuthDesc)

        tid = int(request['tid'])
        if tid == 0:
            tid = self.request.tid

        yield login_delay(tid)

        self.state.tokens.use(request['token'])

        session = yield login(tid,
                              request['username'],
                              request['password'],
                              request['authcode'],
                              self.request.client_using_tor,
                              self.request.client_ip)

        State.log(tid=tid, type='login', user_id=session.user_id)

        if tid != self.request.tid:
            returnValue({
                'redirect': 'https://%s/#/login?token=%s' % (State.tenant_cache[tid].hostname, session.id)
            })

        returnValue(session.serialize())
コード例 #2
0
def login_failure(tid, role, whistleblower=False):
    Settings.failed_login_attempts[tid] = Settings.failed_login_attempts.get(
        tid, 0) + 1

    State.log(tid=tid,
              type='whistleblower_login_failure'
              if whistleblower else 'login_failure')

    raise errors.InvalidAuthentication
コード例 #3
0
ファイル: authentication.py プロジェクト: hevelius/GlobaLeaks
    def delete(self):
        """
        Logout
        """
        if self.current_user.user_role == 'whistleblower':
            State.log(tid=self.current_user.tid,  type='whistleblower_logout')
        else:
            State.log(tid=self.current_user.tid,  type='logout', user_id=self.current_user.user_id)

        del Sessions[self.current_user.id]
コード例 #4
0
def reset_submissions(session, tid, user_id):
    """
    Transaction to reset the submissions of the specified tenant

    :param session: An ORM session
    :param tid: A tenant ID
    """
    session.query(Config).filter(Config.tid == tid, Config.var_name == 'counter_submissions').update({'value': 0})

    db_del(session, InternalTip, InternalTip.tid==tid)

    State.log(tid=tid, type='reset_reports', user_id=user_id)
コード例 #5
0
ファイル: authentication.py プロジェクト: hevelius/GlobaLeaks
    def post(self):
        request = self.validate_message(self.request.content.read(), requests.ReceiptAuthDesc)

        yield login_delay(self.request.tid)

        self.state.tokens.use(request['token'])

        connection_check(self.request.tid, self.request.client_ip,
                         'whistleblower', self.request.client_using_tor)

        session = yield login_whistleblower(self.request.tid, request['receipt'])

        State.log(tid=session.tid,  type='whistleblower_login')

        returnValue(session.serialize())
コード例 #6
0
ファイル: user.py プロジェクト: hevelius/GlobaLeaks
def set_user_password(tid, user, password, cc):
    # Regenerate the password hash only if different from the best choice on the platform
    if user.hash_alg != 'ARGON2':
        user.hash_alg = 'ARGON2'
        user.salt = GCE.generate_salt()

    password_hash = GCE.hash_password(password, user.salt)

    # Check that the new password is different form the current password
    if user.password == password_hash:
        raise errors.PasswordReuseError

    user.password = password_hash
    user.password_change_date = datetime_now()

    State.log(tid=tid,
              type='change_password',
              user_id=user.id,
              object_id=user.id)

    if not State.tenant_cache[tid].encryption and cc == '':
        return None

    enc_key = GCE.derive_key(password.encode(), user.salt)
    if not cc:
        # The first password change triggers the generation
        # of the user encryption private key and its backup
        cc, user.crypto_pub_key = GCE.generate_keypair()
        user.crypto_bkp_key, user.crypto_rec_key = GCE.generate_recovery_key(
            cc)

    user.crypto_prv_key = Base64Encoder.encode(
        GCE.symmetric_encrypt(enc_key, cc))

    if State.tenant_cache[1].crypto_escrow_pub_key:
        user.crypto_escrow_bkp1_key = Base64Encoder.encode(
            GCE.asymmetric_encrypt(State.tenant_cache[1].crypto_escrow_pub_key,
                                   cc))

    if State.tenant_cache[tid].crypto_escrow_pub_key:
        user.crypto_escrow_bkp2_key = Base64Encoder.encode(
            GCE.asymmetric_encrypt(
                State.tenant_cache[tid].crypto_escrow_pub_key, cc))

    return cc
コード例 #7
0
def db_admin_update_user(session, tid, user_session, user_id, request, language):
    """
    Transaction for updating an existing user

    :param session: An ORM session
    :param tid: A tenant ID
    :param user_session: The current user session
    :param user_id: The ID of the user to update
    :param request: The request data
    :param language: The language of the request
    :return: The serialized descriptor of the updated object
    """
    fill_localized_keys(request, models.User.localized_keys, language)

    user = db_get_user(session, tid, user_id)

    user.update(request)

    password = request['password']
    if password and (not user.crypto_pub_key or user_session.ek):
        if user.crypto_pub_key and user_session.ek:
            enc_key = GCE.derive_key(password.encode(), user.salt)
            crypto_escrow_prv_key = GCE.asymmetric_decrypt(user_session.cc, Base64Encoder.decode(user_session.ek))

            if user_session.user_tid == 1:
                user_cc = GCE.asymmetric_decrypt(crypto_escrow_prv_key, Base64Encoder.decode(user.crypto_escrow_bkp1_key))
            else:
                user_cc = GCE.asymmetric_decrypt(crypto_escrow_prv_key, Base64Encoder.decode(user.crypto_escrow_bkp2_key))

            user.crypto_prv_key = Base64Encoder.encode(GCE.symmetric_encrypt(enc_key, user_cc))

        if user.hash_alg != 'ARGON2':
            user.hash_alg = 'ARGON2'
            user.salt = GCE.generate_salt()

        user.password = GCE.hash_password(password, user.salt)
        user.password_change_date = datetime_now()

        State.log(tid=tid, type='change_password', user_id=user_session.user_id, object_id=user_id)

    # The various options related in manage PGP keys are used here.
    parse_pgp_options(user, request)

    return user_serialize_user(session, user, language)
コード例 #8
0
def perform_tips_operation(session, tid, receiver_id, operation, rtips_ids):
    """
    Transaction for performing operation on submissions (postpone/delete)

    :param session: An ORM session
    :param tid: A tenant ID
    :param receiver_id: A recipient ID
    :param operation: An operation command (postpone/delete)
    :param rtips_ids: The set of submissions on which performing the specified operation
    """
    receiver = db_get(session, models.User, models.User.id == receiver_id)

    can_postpone_expiration = State.tenant_cache[
        tid].can_postpone_expiration or receiver.can_postpone_expiration
    can_delete_submission = State.tenant_cache[
        tid].can_delete_submission or receiver.can_delete_submission

    itips = session.query(models.InternalTip) \
                   .filter(models.ReceiverTip.receiver_id == receiver_id,
                           models.ReceiverTip.id.in_(rtips_ids),
                           models.InternalTip.id == models.ReceiverTip.internaltip_id,
                           models.InternalTip.tid == tid)

    if operation == 'postpone' and can_postpone_expiration:
        for itip in itips:
            db_postpone_expiration(session, itip)

    elif operation == 'delete' and can_delete_submission:
        itip_ids = [itip.id for itip in itips]

        for itip_id in itip_ids:
            State.log(tid=tid,
                      type='delete_report',
                      user_id=receiver_id,
                      object_id=itip_id)

        db_del(session, models.InternalTip,
               models.InternalTip.id.in_(itip_ids))

    else:
        raise errors.ForbiddenOperation
コード例 #9
0
def delete_rtip(session, tid, user_id, rtip_id):
    """
    Transaction for deleting a submission

    :param session: An ORM session
    :param tid: A tenant ID of the user performing the operation
    :param user_id: A user ID of the user performing the operation
    :param rtip_id: A rtip ID of the submission object of the operation
    """
    rtip, itip = db_access_rtip(session, tid, user_id, rtip_id)

    receiver = db_get(session, models.User, models.User.id == rtip.receiver_id)

    if not (State.tenant_cache[tid].can_delete_submission
            or receiver.can_delete_submission):
        raise errors.ForbiddenOperation

    State.log(tid=tid,
              type='delete_report',
              user_id=user_id,
              object_id=itip.id)

    db_delete_itip(session, itip.id)
コード例 #10
0
def db_create_submission(session, tid, request, token, client_using_tor):
    encryption = db_get(
        session, models.Config,
        (models.Config.tid == tid, models.Config.var_name == 'encryption'))

    crypto_is_available = encryption.value

    tenant = db_get(session, models.Tenant, models.Tenant.id == tid)

    context, questionnaire = db_get(
        session, (models.Context, models.Questionnaire),
        (models.Context.id == request['context_id'], models.Questionnaire.id
         == models.Context.questionnaire_id))

    answers = request['answers']
    steps = db_get_questionnaire(session, tid, questionnaire.id, None)['steps']
    questionnaire_hash = db_archive_questionnaire_schema(session, steps)

    crypto_tip_pub_key = ''

    receivers = []
    for r in session.query(models.User).filter(
            models.User.id.in_(request['receivers'])):
        if crypto_is_available:
            if r.crypto_pub_key:
                # This is the regular condition of systems setup on Globaleaks 4
                # Since this version, encryption is enabled by default and
                # users need to perform their first access before they
                # could receive reports.
                receivers.append(r)
            elif encryption.update_date != datetime_null():
                # This is the exceptional condition of systems setup when
                # encryption was implemented via PGP.
                # For continuity reason of those production systems
                # encryption could not be enforced.
                receivers.append(r)
                crypto_is_available = False
        else:
            receivers.append(r)

    if not receivers:
        raise errors.InputValidationError(
            "Unable to deliver the submission to at least one recipient")

    if 0 < context.maximum_selectable_receivers < len(request['receivers']):
        raise errors.InputValidationError(
            "The number of recipients selected exceed the configured limit")

    if crypto_is_available:
        crypto_tip_prv_key, crypto_tip_pub_key = GCE.generate_keypair()

    itip = models.InternalTip()
    itip.tid = tid
    itip.status = 'new'
    itip.crypto_tip_pub_key = crypto_tip_pub_key

    itip.progressive = db_assign_submission_progressive(session, tid)

    if context.tip_timetolive > 0:
        itip.expiration_date = get_expiration(context.tip_timetolive)

    # Evaluate the score level
    itip.total_score = request['total_score']

    # The status https is used to keep track of the security level adopted by the whistleblower
    itip.https = not client_using_tor
    itip.mobile = request['mobile']

    itip.context_id = context.id
    itip.enable_two_way_comments = context.enable_two_way_comments
    itip.enable_two_way_messages = context.enable_two_way_messages
    itip.enable_attachments = context.enable_attachments

    x = session.query(models.Field, models.FieldAttr.value) \
               .filter(models.Field.template_id == 'whistleblower_identity',
                       models.Field.step_id == models.Step.id,
                       models.Step.questionnaire_id == context.questionnaire_id,
                       models.FieldAttr.field_id == models.Field.id,
                       models.FieldAttr.name == 'visibility_subject_to_authorization').one_or_none()

    whistleblower_identity = None
    can_access_whistleblower_identity = True

    if x:
        whistleblower_identity = x[0]
        can_access_whistleblower_identity = not x[1]

    itip.enable_whistleblower_identity = whistleblower_identity is not None

    session.add(itip)
    session.flush()

    # Evaluate if the whistleblower tip should be generated
    if ((not State.tenant_cache[tid].enable_scoring_system)
            or (context.score_threshold_receipt == 0)
            or (context.score_threshold_receipt == 1 and itip.total_score >= 2)
            or
        (context.score_threshold_receipt == 2 and itip.total_score == 3)):

        receipt = GCE.generate_receipt()
        receipt_salt = State.tenant_cache[tid].receipt_salt

        wbtip = models.WhistleblowerTip()
        wbtip.id = itip.id
        wbtip.tid = tid
        wbtip.hash_alg = 'ARGON2'
        wbtip.receipt_hash = GCE.hash_password(receipt, receipt_salt)

        # Evaluate if the whistleblower tip should be encrypted
        if crypto_is_available:
            crypto_tip_prv_key, itip.crypto_tip_pub_key = GCE.generate_keypair(
            )
            wb_key = GCE.derive_key(receipt.encode(), receipt_salt)
            wb_prv_key, wb_pub_key = GCE.generate_keypair()
            wbtip.crypto_prv_key = Base64Encoder.encode(
                GCE.symmetric_encrypt(wb_key, wb_prv_key))
            wbtip.crypto_pub_key = wb_pub_key
            wbtip.crypto_tip_prv_key = Base64Encoder.encode(
                GCE.asymmetric_encrypt(wb_pub_key, crypto_tip_prv_key))

        session.add(wbtip)
    else:
        receipt = ''

    # Apply special handling to the whistleblower identity question
    if itip.enable_whistleblower_identity and request[
            'identity_provided'] and answers[whistleblower_identity.id]:
        if crypto_is_available:
            wbi = base64.b64encode(
                GCE.asymmetric_encrypt(
                    itip.crypto_tip_pub_key,
                    json.dumps(answers[whistleblower_identity.id]
                               [0]).encode())).decode()
        else:
            wbi = answers[whistleblower_identity.id][0]

        answers[whistleblower_identity.id] = ''

        db_set_internaltip_data(session, itip.id, 'whistleblower_identity',
                                wbi)

    if crypto_is_available:
        answers = base64.b64encode(
            GCE.asymmetric_encrypt(
                itip.crypto_tip_pub_key,
                json.dumps(answers, cls=JSONEncoder).encode())).decode()

    db_set_internaltip_answers(session, itip.id, questionnaire_hash, answers)

    for uploaded_file in token.uploaded_files:
        if not itip.enable_attachments:
            break

        if uploaded_file['id'] in request['removed_files']:
            continue

        if crypto_is_available:
            for k in ['name', 'type', 'size']:
                uploaded_file[k] = base64.b64encode(
                    GCE.asymmetric_encrypt(itip.crypto_tip_pub_key,
                                           str(uploaded_file[k])))

        new_file = models.InternalFile()
        new_file.tid = tid
        new_file.name = uploaded_file['name']
        new_file.content_type = uploaded_file['type']
        new_file.size = uploaded_file['size']
        new_file.internaltip_id = itip.id
        new_file.filename = uploaded_file['filename']
        new_file.submission = uploaded_file['submission']
        session.add(new_file)

    for user in receivers:
        if crypto_is_available:
            _tip_key = GCE.asymmetric_encrypt(user.crypto_pub_key,
                                              crypto_tip_prv_key)
        else:
            _tip_key = b''

        db_create_receivertip(session, user, itip,
                              can_access_whistleblower_identity, _tip_key)

    State.log(tid=tid, type='whistleblower_new_report')

    return {'receipt': receipt, 'score': itip.total_score}