178 lines
4.9 KiB
Python
178 lines
4.9 KiB
Python
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
|