def import_receivers(store, submission, receiver_id_list): context = submission.context if not len(receiver_id_list): raise errors.SubmissionValidationFailure( "needed almost one receiver selected [1]") if context.maximum_selectable_receivers and \ len(receiver_id_list) > context.maximum_selectable_receivers: raise errors.InvalidInputFormat( "provided an invalid number of receivers") for receiver in store.find(models.Receiver, In(models.Receiver.id, receiver_id_list)): if context not in receiver.contexts: raise errors.InvalidInputFormat( "forged receiver selection, you fuzzer! <:") if not GLSettings.memory_copy.allow_unencrypted and receiver.user.pgp_key_status != u'enabled': raise errors.SubmissionValidationFailure( "the platform does not allow selection of receivers with encryption disabled" ) continue submission.receivers.add(receiver) log.debug("+receiver [%s] In tip (%s) #%d" % \ (receiver.user.name, submission.id, submission.receivers.count() )) if submission.receivers.count() == 0: raise errors.SubmissionValidationFailure( "needed almost one receiver selected [2]")
def import_receivers(store, submission, receiver_id_list): context = submission.context if not len(receiver_id_list): log.err("Receivers required to be selected, not empty") raise errors.SubmissionValidationFailure("needed almost one receiver selected") if context.maximum_selectable_receivers and \ len(receiver_id_list) > context.maximum_selectable_receivers: raise errors.InvalidInputFormat("provided an invalid number of receivers") for receiver in store.find(Receiver, In(Receiver.id, receiver_id_list)): if context not in receiver.contexts: raise errors.InvalidInputFormat("forged receiver selection, you fuzzer! <:") try: if not GLSettings.memory_copy.allow_unencrypted and \ receiver.pgp_key_status != u'enabled': log.err("Encrypted only submissions are supported. Cannot select [%s]" % receiver.id) continue submission.receivers.add(receiver) except Exception as excep: log.err("Receiver %s can't be assigned to the tip [%s]" % (receiver.id, excep)) continue log.debug("+receiver [%s] In tip (%s) #%d" % \ (receiver.name, submission.id, submission.receivers.count() )) if submission.receivers.count() == 0: log.err("Receivers required to be selected, not empty") raise errors.SubmissionValidationFailure("needed at least one receiver selected [2]")
def verify_fields_recursively(fields, wb_fields): for f in fields: if f not in wb_fields: raise errors.SubmissionValidationFailure( "missing field (no structure present): %s" % f) if fields[f]['required'] and ('value' not in wb_fields[f] or wb_fields[f]['value'] == ''): raise errors.SubmissionValidationFailure( "missing required field (no value provided): %s" % f) if isinstance(wb_fields[f]['value'], unicode): if len(wb_fields[f] ['value']) > GLSettings.memory_copy.maximum_textsize: raise errors.InvalidInputFormat( "field value overcomes size limitation") indexed_fields = {} for f_c in fields[f]['children']: indexed_fields[f_c['id']] = copy.deepcopy(f_c) indexed_wb_fields = {} for f_c in wb_fields[f]['children']: indexed_wb_fields[f_c['id']] = copy.deepcopy(f_c) verify_fields_recursively(indexed_fields, indexed_wb_fields) for wbf in wb_fields: if wbf not in fields: raise errors.SubmissionValidationFailure( "provided unexpected field %s" % wbf)
def db_create_submission(store, request, uploaded_files, client_using_tor, language): answers = request['answers'] context = store.find(models.Context, models.Context.id == request['context_id']).one() if not context: raise errors.ContextIdNotFound submission = models.InternalTip() submission.progressive = db_assign_submission_progressive(store) if context.tip_timetolive > -1: submission.expiration_date = get_expiration(context.tip_timetolive) else: submission.expiration_date = datetime_never() # this is get from the client as it the only possibility possible # that would fit with the end to end submission. # the score is only an indicator and not a critical information so we can accept to # be fooled by the malicious user. submission.total_score = request['total_score'] # The status tor2web is used to keep track of the security level adopted by the whistleblower submission.tor2web = not client_using_tor submission.context_id = context.id submission.enable_two_way_comments = context.enable_two_way_comments submission.enable_two_way_messages = context.enable_two_way_messages submission.enable_attachments = context.enable_attachments submission.enable_whistleblower_identity = context.questionnaire.enable_whistleblower_identity if submission.enable_whistleblower_identity and request[ 'identity_provided']: submission.identity_provided = True submission.identity_provided_date = datetime_now() try: questionnaire = db_get_context_steps(store, context.id, None) questionnaire_hash = unicode(sha256(json.dumps(questionnaire))) submission.questionnaire_hash = questionnaire_hash submission.preview = extract_answers_preview(questionnaire, answers) store.add(submission) db_archive_questionnaire_schema(store, questionnaire, questionnaire_hash) db_save_questionnaire_answers(store, submission.id, answers) except Exception as excep: log.err("Submission create: fields validation fail: %s" % excep) raise excep try: for filedesc in uploaded_files: new_file = models.InternalFile() new_file.name = filedesc['name'] new_file.description = "" new_file.content_type = filedesc['type'] new_file.size = filedesc['size'] new_file.internaltip_id = submission.id new_file.submission = filedesc['submission'] new_file.file_path = filedesc['path'] store.add(new_file) log.debug("=> file associated %s|%s (%d bytes)" % (new_file.name, new_file.content_type, new_file.size)) except Exception as excep: log.err("Submission create: unable to create db entry for files: %s" % excep) raise excep receipt, wbtip = db_create_whistleblowertip(store, submission) if submission.context.maximum_selectable_receivers > 0 and \ len(request['receivers']) > submission.context.maximum_selectable_receivers: raise errors.SubmissionValidationFailure( "selected an invalid number of recipients") rtips = [] for receiver in store.find(models.Receiver, In(models.Receiver.id, request['receivers'])): if submission.context not in receiver.contexts: continue if not GLSettings.memory_copy.allow_unencrypted and len( receiver.user.pgp_key_public) == 0: continue rtips.append(db_create_receivertip(store, receiver, submission)) if len(rtips) == 0: raise errors.SubmissionValidationFailure("need at least one recipient") log.debug("The finalized submission had created %d models.ReceiverTip(s)" % len(rtips)) submission_dict = serialize_usertip(store, wbtip, language) submission_dict.update({'receipt': receipt}) return submission_dict
def db_create_submission(store, request, uploaded_files, client_using_tor): answers = request['answers'] context, questionnaire = store.find( (models.Context, models.Questionnaire), models.Context.id == request['context_id'], models.Questionnaire.id == models.Context.questionnaire_id).one() if not context: raise errors.ModelNotFound(models.Context) steps = db_get_questionnaire(store, questionnaire.id, None)['steps'] questionnaire_hash = unicode(sha256(json.dumps(steps))) submission = models.InternalTip() submission.progressive = db_assign_submission_progressive(store) if context.tip_timetolive > -1: submission.expiration_date = get_expiration(context.tip_timetolive) else: submission.expiration_date = datetime_never() # this is get from the client as it the only possibility possible # that would fit with the end to end submission. # the score is only an indicator and not a critical information so we can accept to # be fooled by the malicious user. submission.total_score = request['total_score'] # The status tor2web is used to keep track of the security level adopted by the whistleblower submission.tor2web = not client_using_tor submission.context_id = context.id submission.enable_two_way_comments = context.enable_two_way_comments submission.enable_two_way_messages = context.enable_two_way_messages submission.enable_attachments = context.enable_attachments submission.enable_whistleblower_identity = questionnaire.enable_whistleblower_identity if submission.enable_whistleblower_identity and request[ 'identity_provided']: submission.identity_provided = True submission.identity_provided_date = datetime_now() submission.questionnaire_hash = questionnaire_hash submission.preview = extract_answers_preview(steps, answers) store.add(submission) db_archive_questionnaire_schema(store, steps, questionnaire_hash) db_save_questionnaire_answers(store, submission.id, answers) for filedesc in uploaded_files: new_file = models.InternalFile() new_file.name = filedesc['name'] new_file.description = "" new_file.content_type = filedesc['type'] new_file.size = filedesc['size'] new_file.internaltip_id = submission.id new_file.submission = filedesc['submission'] new_file.file_path = filedesc['path'] store.add(new_file) log.debug("=> file associated %s|%s (%d bytes)", new_file.name, new_file.content_type, new_file.size) receipt = db_create_whistleblowertip(store, submission) if context.maximum_selectable_receivers > 0 and \ len(request['receivers']) > context.maximum_selectable_receivers: raise errors.SubmissionValidationFailure( "selected an invalid number of recipients") rtips_count = 0 for receiver, user, in store.find( (models.Receiver, models.User), In(models.Receiver.id, request['receivers']), models.ReceiverContext.receiver_id == models.Receiver.id, models.ReceiverContext.context_id == context.id, models.User.id == models.Receiver.id): if user.pgp_key_public or GLSettings.memory_copy.allow_unencrypted: db_create_receivertip(store, receiver, submission) rtips_count += 1 if rtips_count == 0: raise errors.SubmissionValidationFailure("need at least one recipient") log.debug("The finalized submission had created %d models.ReceiverTip(s)", rtips_count) return {'receipt': receipt}