from django.shortcuts import render from django.contrib.auth.mixins import AccessMixin from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView 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 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') 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