from django.shortcuts import render from django.contrib.auth.mixins import AccessMixin from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView, TemplateView import requests import magic from django.conf import settings from django.core.validators import URLValidator, ValidationError from django.http import Http404, HttpResponse from django.views.generic import View import base64 from cryptography.fernet import Fernet from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC import os, six from recoverdir.models import RecoverDirSetting from datetime import datetime from django.contrib import messages from django.shortcuts import render, redirect, reverse def _get_setting(name): setting_name = "DEFF_{}".format(name) return os.getenv(setting_name, getattr(settings, setting_name, None)) def get_bytes(v): if isinstance(v, six.string_types): return bytes(v.encode("utf-8")) if isinstance(v, bytes): return v raise TypeError( "SALT & PASSWORD must be specified as strings that convert nicely to " "bytes." ) SALT = get_bytes(_get_setting("SALT")) PASSWORD = get_bytes(_get_setting("PASSWORD")) FETCH_URL_NAME = _get_setting("FETCH_URL_NAME") class Cryptographer(object): _fernet = Fernet(base64.urlsafe_b64encode(PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=SALT, iterations=100000, backend=default_backend() ).derive(PASSWORD))) @classmethod def encrypted(cls, content): return cls._fernet.encrypt(content) @classmethod def decrypted(cls, content): return cls._fernet.decrypt(content) def registerdone(request): return render (request, 'users/registercomplete.html') # TASK: Hier den Abruf von Dokumenten bei eingeloggtem Recover-Datum weniger als 10 Minuten implementieren class GetCryptFileRecover(TemplateView): def get(self, request, *args, **kwargs): try: settings = RecoverDirSetting.objects.filter(agency_id=kwargs['agpk'])[0] except IndexError: messages.warning(self.request, f'Diese Agentur hat keine Notfallhilfe.') return redirect('load-rd-external') if settings.lastlogg == None: messages.warning(self.request, f'Bitte loggen Sie sich erneut ein!') return redirect('load-rd-external') else: now = datetime.now() time_delta = (now-settings.lastlogg) total_seconds = time_delta.total_seconds() minutes = total_seconds/60 if(settings.lastlogg != None and minutes < 10): # LOGIN OK AND LOGIN EARLIER THAN 10 MINUTES path = kwargs.get("path") # No path? You're boned. Move along. if not path: raise Http404 if self._is_url(path): content = requests.get(path, stream=True).raw.read() else: # Normalise the path to strip out naughty attempts #path = os.path.normpath(path).replace(settings.MEDIA_URL, settings.MEDIA_ROOT, 1) path = "media/" + path # Evil path request! #if not path.startswith(settings.MEDIA_ROOT): # print("404 startswith") # raise Http404 # The file requested doesn't exist locally. A legit 404 if not os.path.exists(path): raise Http404 with open(path, "rb") as f: content = f.read() content = Cryptographer.decrypted(content) return HttpResponse(content, content_type=magic.Magic(mime=True).from_buffer(content)) else: # LOGIN TO OLD - SET LASTLOGG TO NONE AND SEND MESSAGE settings.lastlogg = None settings.save() messages.warning(self.request, f'Bitte loggen Sie sich erneut ein!') return redirect('load-rd-external') @staticmethod def _is_url(path): try: URLValidator()(path) return True except ValidationError: return False class GetCryptFile(DetailView): def get(self, request, *args, **kwargs): if(self.request.user.has_perm("users.recoverdirmanager")): path = kwargs.get("path") # No path? You're boned. Move along. if not path: raise Http404 if self._is_url(path): content = requests.get(path, stream=True).raw.read() else: # Normalise the path to strip out naughty attempts path = os.path.normpath(path).replace(settings.MEDIA_URL, settings.MEDIA_ROOT, 1) path = "media/" + path # Evil path request! #if not path.startswith(settings.MEDIA_ROOT): # print("404 startswith") # raise Http404 # The file requested doesn't exist locally. A legit 404 if not os.path.exists(path): raise Http404 with open(path, "rb") as f: content = f.read() content = Cryptographer.decrypted(content) return HttpResponse(content, content_type=magic.Magic(mime=True).from_buffer(content)) else: return render(request, 'cloud/noentrie.html') @staticmethod def _is_url(path): try: URLValidator()(path) return True except ValidationError: return False