class FileserverRevokeDownloadSerializer(serializers.Serializer): file_transfer_id = UUIDField(required=True) ticket = serializers.CharField(required=True) ticket_nonce = serializers.CharField(required=True) ip_address = serializers.CharField(required=True) def validate(self, attrs: dict) -> dict: file_transfer_id = attrs.get('file_transfer_id') ticket_encrypted = attrs.get('ticket') ticket_nonce = attrs.get('ticket_nonce') ip_address = attrs.get('ip_address') try: file_transfer = File_Transfer.objects.select_related('user').\ only('chunk_count', 'size', 'chunk_count_transferred', 'size_transferred', 'file_id', 'shard_id', 'secret_key', 'user__is_active', 'user_id').\ get(pk=file_transfer_id, type='download') except File_Transfer.DoesNotExist: msg = _('Filetransfer does not exist.') raise exceptions.ValidationError(msg) if not file_transfer.user.is_active: msg = _('User inactive.') raise exceptions.ValidationError(msg) try: ticket_json = decrypt(file_transfer.secret_key, ticket_encrypted, ticket_nonce) except: msg = _('Malformed ticket. Decryption failed.') raise exceptions.ValidationError(msg) ticket = json.loads(ticket_json) if 'hash_checksum' not in ticket: msg = _('Malformed ticket. Blake2b hash missing.') raise exceptions.ValidationError(msg) hash_checksum = ticket['hash_checksum'].lower() count_cmsl = Fileserver_Cluster_Member_Shard_Link.objects.select_related('member')\ .filter(member__valid_till__gt=timezone.now() - timedelta(seconds=settings.FILESERVER_ALIVE_TIMEOUT), shard__active=True, member=self.context['request'].user, shard_id=file_transfer.shard_id).count() if count_cmsl != 1: msg = _('Permission denied.') raise exceptions.ValidationError(msg) try: file_chunk = File_Chunk.objects.get(hash_checksum=hash_checksum) except File_Chunk.DoesNotExist: msg = "NO_PERMISSION_OR_NOT_EXIST" raise exceptions.ValidationError(msg) attrs['file_transfer'] = file_transfer attrs['file_chunk'] = file_chunk return attrs
class UpdateUserSerializer(serializers.Serializer): user_id = UUIDField(required=True) is_active = BooleanField(required=False) is_email_active = BooleanField(required=False) is_superuser = BooleanField(required=False) email = serializers.EmailField(required=False, error_messages={ 'invalid': 'INVALID_EMAIL_FORMAT' }) def validate(self, attrs: dict) -> dict: user_id = attrs.get('user_id') is_active = attrs.get('is_active', None) is_email_active = attrs.get('is_email_active', None) is_superuser = attrs.get('is_superuser', None) email = attrs.get('email') try: user = User.objects.get(pk=user_id) except User.DoesNotExist: msg = "NO_PERMISSION_OR_NOT_EXIST" raise exceptions.ValidationError(msg) if email is not None: email = email.lower().strip() if len(settings.REGISTRATION_EMAIL_FILTER) > 0: email_prefix, domain = email.split("@") if domain not in settings.REGISTRATION_EMAIL_FILTER: msg = _('E-Mail not allowed to register.') raise exceptions.ValidationError(msg) # generate bcrypt with static salt. # I know its bad to use static salts, but its the best solution I could come up with, # if you want to store emails encrypted while not having to decrypt all emails for duplicate email hunt # Im aware that this allows attackers with this fix salt to "mass" attack all emails. # if you have a better solution, please let me know. email_bcrypt_full = bcrypt.hashpw(email.encode(), settings.EMAIL_SECRET_SALT.encode()) email_bcrypt = email_bcrypt_full.decode().replace(settings.EMAIL_SECRET_SALT, '', 1) if User.objects.filter(email_bcrypt=email_bcrypt).exclude(pk=user_id).exists(): msg = _('E-Mail already exists.') raise exceptions.ValidationError(msg) attrs['email_bcrypt'] = email_bcrypt # normally encrypt emails, so they are not stored in plaintext with a random nonce email = encrypt_with_db_secret(email) attrs['user'] = user attrs['email'] = email attrs['is_active'] = is_active attrs['is_email_active'] = is_email_active attrs['is_superuser'] = is_superuser return attrs
class DeleteYubikeySerializer(serializers.Serializer): yubikey_otp_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: yubikey_otp_id = attrs.get('yubikey_otp_id') try: yubikey_otp = Yubikey_OTP.objects.get(pk=yubikey_otp_id) except Yubikey_OTP.DoesNotExist: msg = "NO_PERMISSION_OR_NOT_EXIST" raise exceptions.ValidationError(msg) attrs['yubikey_otp'] = yubikey_otp return attrs
class DeleteEmergencyCodeSerializer(serializers.Serializer): emergency_code_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: emergency_code_id = attrs.get('emergency_code_id') try: emergency_code = Emergency_Code.objects.get(pk=emergency_code_id) except Emergency_Code.DoesNotExist: msg = _("NO_PERMISSION_OR_NOT_EXIST") raise exceptions.ValidationError(msg) attrs['emergency_code'] = emergency_code return attrs
class DeleteDuoSerializer(serializers.Serializer): duo_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: duo_id = attrs.get('duo_id') try: duo = Duo.objects.get(pk=duo_id) except Duo.DoesNotExist: msg = "NO_PERMISSION_OR_NOT_EXIST" raise exceptions.ValidationError(msg) attrs['duo'] = duo return attrs
class DeleteSessionSerializer(serializers.Serializer): session_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: session_id = attrs.get('session_id') try: token = Token.objects.get(id=session_id) except Token.DoesNotExist: msg = _("NO_PERMISSION_OR_NOT_EXIST") raise exceptions.ValidationError(msg) attrs['token'] = token return attrs
class DeleteGASerializer(serializers.Serializer): google_authenticator_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: google_authenticator_id = attrs.get('google_authenticator_id') try: google_authenticator = Google_Authenticator.objects.get(pk=google_authenticator_id) except Google_Authenticator.DoesNotExist: msg = _("NO_PERMISSION_OR_NOT_EXIST") raise exceptions.ValidationError(msg) attrs['google_authenticator'] = google_authenticator return attrs
class DeleteUserSerializer(serializers.Serializer): user_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: user_id = attrs.get('user_id') try: user = User.objects.get(pk=user_id) except User.DoesNotExist: msg = "NO_PERMISSION_OR_NOT_EXIST" raise exceptions.ValidationError(msg) attrs['user'] = user return attrs
class DeleteMembershipSerializer(serializers.Serializer): membership_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: membership_id = attrs.get('membership_id') try: membership = User_Group_Membership.objects.get(id=membership_id) except User_Group_Membership.DoesNotExist: msg = "NO_PERMISSION_OR_NOT_EXIST" raise exceptions.ValidationError(msg) attrs['membership'] = membership return attrs
class DeleteGroupSerializer(serializers.Serializer): group_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: group_id = attrs.get('group_id') try: group = Group.objects.get(id=group_id) except Group.DoesNotExist: msg = "NO_PERMISSION_OR_NOT_EXIST" raise exceptions.ValidationError(msg) attrs['group'] = group return attrs
class DeleteRecoveryCodeSerializer(serializers.Serializer): recovery_code_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: recovery_code_id = attrs.get('recovery_code_id') try: recovery_code = Recovery_Code.objects.get(pk=recovery_code_id) except Recovery_Code.DoesNotExist: msg = "NO_PERMISSION_OR_NOT_EXIST" raise exceptions.ValidationError(msg) attrs['recovery_code'] = recovery_code return attrs
class DeleteUserSerializer(serializers.Serializer): user_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: user_id = attrs.get('user_id') try: user = User.objects.get(pk=user_id) except User.DoesNotExist: msg = _( "You don't have permission to access or it does not exist.") raise exceptions.ValidationError(msg) attrs['user'] = user return attrs
class DeleteYubikeySerializer(serializers.Serializer): yubikey_otp_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: yubikey_otp_id = attrs.get('yubikey_otp_id') try: yubikey_otp = Yubikey_OTP.objects.get(pk=yubikey_otp_id) except Yubikey_OTP.DoesNotExist: msg = _( "You don't have permission to access or it does not exist.") raise exceptions.ValidationError(msg) attrs['yubikey_otp'] = yubikey_otp return attrs
class DeleteSessionSerializer(serializers.Serializer): session_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: session_id = attrs.get('session_id') try: token = Token.objects.get(id=session_id) except Token.DoesNotExist: msg = _( "You don't have permission to access or it does not exist.") raise exceptions.ValidationError(msg) attrs['token'] = token return attrs
class DeleteRecoveryCodeSerializer(serializers.Serializer): recovery_code_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: recovery_code_id = attrs.get('recovery_code_id') try: recovery_code = Recovery_Code.objects.get(pk=recovery_code_id) except Recovery_Code.DoesNotExist: msg = _( "You don't have permission to access or it does not exist.") raise exceptions.ValidationError(msg) attrs['recovery_code'] = recovery_code return attrs
class DeleteDuoSerializer(serializers.Serializer): duo_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: duo_id = attrs.get('duo_id') try: duo = Duo.objects.get(pk=duo_id) except Duo.DoesNotExist: msg = _( "You don't have permission to access or it does not exist.") raise exceptions.ValidationError(msg) attrs['duo'] = duo return attrs
class DeleteGroupSerializer(serializers.Serializer): group_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: group_id = attrs.get('group_id') try: group = Group.objects.get(id=group_id) except Group.DoesNotExist: msg = _( "You don't have permission to access or it does not exist.") raise exceptions.ValidationError(msg) attrs['group'] = group return attrs
class DeleteMembershipSerializer(serializers.Serializer): membership_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: membership_id = attrs.get('membership_id') try: membership = User_Group_Membership.objects.get(id=membership_id) except User_Group_Membership.DoesNotExist: msg = _( "You don't have permission to access or it does not exist.") raise exceptions.ValidationError(msg) attrs['membership'] = membership return attrs
class DeleteGASerializer(serializers.Serializer): google_authenticator_id = UUIDField(required=True) def validate(self, attrs: dict) -> dict: google_authenticator_id = attrs.get('google_authenticator_id') try: google_authenticator = Google_Authenticator.objects.get( pk=google_authenticator_id) except Google_Authenticator.DoesNotExist: msg = _( "You don't have permission to access or it does not exist.") raise exceptions.ValidationError(msg) attrs['google_authenticator'] = google_authenticator return attrs
class FileserverAuthorizeUploadSerializer(serializers.Serializer): file_transfer_id = UUIDField(required=True) ticket = serializers.CharField(required=True) ticket_nonce = serializers.CharField(required=True) chunk_size = serializers.IntegerField(required=True) hash_checksum = serializers.CharField(required=True) ip_address = serializers.CharField(required=True) def validate(self, attrs: dict) -> dict: file_transfer_id = attrs.get('file_transfer_id') ticket_encrypted = attrs.get('ticket') ticket_nonce = attrs.get('ticket_nonce') chunk_size = attrs.get('chunk_size', 0) hash_checksum = attrs.get('hash_checksum', '').lower() ip_address = attrs.get('ip_address') try: file_transfer = File_Transfer.objects.select_related('user').\ only('chunk_count', 'size', 'chunk_count_transferred', 'size_transferred', 'file_id', 'shard_id', 'secret_key', 'user__is_active', 'user_id').\ get(pk=file_transfer_id, type='upload') except File_Transfer.DoesNotExist: msg = _('Filetransfer does not exist.') raise exceptions.ValidationError(msg) if not file_transfer.user.is_active: msg = _('User inactive.') raise exceptions.ValidationError(msg) try: ticket_json = decrypt(file_transfer.secret_key, ticket_encrypted, ticket_nonce) except: msg = _('Malformed ticket. Decryption failed.') raise exceptions.ValidationError(msg) ticket = json.loads(ticket_json) if 'chunk_position' not in ticket: msg = _('Malformed ticket. Chunk Position missing.') raise exceptions.ValidationError(msg) if 'hash_checksum' not in ticket: msg = _('Malformed ticket. Blake2b hash missing.') raise exceptions.ValidationError(msg) chunk_size_limit = 128 * 1024 * 1024 + 40 if chunk_size > chunk_size_limit: msg = _("Chunk size exceeds limit.") raise exceptions.ValidationError(msg) if chunk_size < 40: msg = _("Chunk size too small.") raise exceptions.ValidationError(msg) chunk_position = ticket['chunk_position'] hash_checksum_ticket = ticket['hash_checksum'].lower() if hash_checksum_ticket != hash_checksum: msg = _('Chunk corrupted.') raise exceptions.ValidationError(msg) count_cmsl = Fileserver_Cluster_Member_Shard_Link.objects.select_related('member')\ .filter(member__valid_till__gt=timezone.now() - timedelta(seconds=settings.FILESERVER_ALIVE_TIMEOUT), shard__active=True, member=self.context['request'].user, shard_id=file_transfer.shard_id).count() if count_cmsl != 1: msg = _('Permission denied.') raise exceptions.ValidationError(msg) if file_transfer.chunk_count_transferred + 1 > file_transfer.chunk_count: msg = _('Chunk count exceeded.') raise exceptions.ValidationError(msg) if file_transfer.size_transferred + chunk_size > file_transfer.size: msg = _('Chunk size exceeded.') raise exceptions.ValidationError(msg) attrs['file_transfer'] = file_transfer attrs['user_id'] = file_transfer.user_id attrs['chunk_position'] = chunk_position attrs['chunk_size'] = chunk_size attrs['hash_checksum'] = hash_checksum return attrs