from django.shortcuts import render, get_object_or_404, redirect from django.http import HttpResponse from django.contrib.auth.forms import AuthenticationForm from django.db.models import Q from django.views.decorators.csrf import csrf_exempt from django.utils import timezone from django.core.files import File from django.db.models.fields.files import FieldFile from .models import Device, Organization, Network from distutils.dir_util import copy_tree import glob import sys import subprocess import os import socket import tempfile import crypt import tarfile def index(request): if request.user.is_authenticated: return redirect("/devices") else: return redirect("/accounts/login") @csrf_exempt def heartbeat(request): device = get_object_or_404(Device, secret=request.POST.get("secret", "")) ip = request.POST.get("ip", "") if ip: device.lasttime = timezone.now() if device.curip: device.curip = ip or device.curip else: device.curip = ip device.save() return HttpResponse("reboot" if device.reboot else "") @csrf_exempt def hosts(request): device = get_object_or_404(Device, secret=request.POST.get("secret", "")) device.reboot = False device.save() return render(request, "manager/hosts", {"device": device}) def ping(request, device_id): if request.user.is_authenticated: device = None ajax = '{\n "status": ' for organization in Organization.objects.filter(users=request.user): device = device or Device.objects.filter(id=device_id, organization=organization) if not device: ajax += "-1" else: try: socket.inet_aton(device[0].curip) ajax += str(int(not os.WEXITSTATUS(os.system("ping -c1 -w1 " + device[0].curip + " > /dev/null 2>&1")))) # This monster is not long enough yet. ajax += ',\n "ip": "%s"' % device[0].curip ajax += ',\n "time": "%s"' % device[0].lasttime except: ajax += "-3" else: ajax += "-2" ajax += "\n}" return HttpResponse(ajax) def devices(request): if request.user.is_authenticated: user = request.user devices = set() orga = None for organization in Organization.objects.filter(users=user): orga = orga or organization for device in Device.objects.filter(organization=organization): devices.add(device) return render(request, "manager/index.html", { "title": "Device Administration", "user": user, "organization": orga, "devices": devices } ) else: return redirect("/") def editdevice(request, device_id): if request.user.is_authenticated: device = None subnets = set() for organization in Organization.objects.filter(users=request.user): device = device or Device.objects.filter(id=device_id, organization=organization) for subnet in Network.objects.filter(organizations=organization): subnets.add(subnet) if not device: return redirect("/") if request.POST.get("subnet", ""): subnet = Network.objects.filter(intip=request.POST.get("subnet", device[0].network.intip)) if subnet[0] in subnets: device[0].name = request.POST.get("name", "") device[0].network = subnet[0] device[0].reboot = True if request.POST.get("reboot", "0") == "True" else False device[0].save() return redirect("/") return render(request, "manager/edit.html", { "title": "Edit Device", "device": device[0], "subnets": subnets } ) else: return redirect("/") def getconfig(request, device_id): BEFORE = os.getcwd() DEVICEDIR = "/opt/vpnmanager/device-config/" SRCDIR = "/opt/openwrt/" if not request.user.is_superuser: return redirect("/") device = get_object_or_404(Device, id=device_id) tempdir = tempfile.TemporaryDirectory() copy_tree(DEVICEDIR, tempdir.name) # Write OpenVPN config with open(tempdir.name + "/etc/openvpn/client.conf", "w") as vpnconf: vpnconf.write(device.vpnconfig) # Write secret with open(tempdir.name + "/etc/vpnsecret", "w") as secret: secret.write('SECRET="%s"' % device.secret) # Write password with open(tempdir.name + "/etc/shadow", "r") as shadow: password = crypt.crypt(device.password, crypt.mksalt(crypt.METHOD_MD5)) shadowin = shadow.read() with open(tempdir.name + "/etc/shadow", "w") as shadowout: shadowout.write(shadowin.replace("$PASSWORD", password)) # Write SSID with open(tempdir.name + "/etc/config/wireless", "r") as wireless: wirein = wireless.read() with open(tempdir.name + "/etc/config/wireless", "w") as wireout: wireout.write(wirein.replace("$SSID", device.serial)) ''' # Generate .tar.gz file with tarfile.open(tempdir.name + ".tar.gz", "w:gz") as tar: tar.add(tempdir.name, arcname=os.path.sep) with open(tempdir.name + ".tar.gz", "rb") as download: response = HttpResponse(download.read(), content_type="application/tar+gzip") response['Content-Disposition'] = 'inline; filename=' + os.path.basename(device.serial + ".tar.gz") return response ''' # Create compilation environment os.system("rm -rf " + SRCDIR + "/files/") os.mkdir(SRCDIR + "/files/") os.system("cp -r " + tempdir.name + "/* " + SRCDIR + "/files/") tempdir.cleanup() os.system("rm " + SRCDIR + "/bin/targets/ar71xx/generic/*") # Build image os.chdir(SRCDIR) try: output = subprocess.check_output(["make", "-j9"]) except: os.chdir(BEFORE) return HttpResponse("Something went wrong building the image file.\n\n" + output) os.chdir(BEFORE) with open(glob.glob(SRCDIR + "/bin/targets/ar71xx/generic/*squashfs-sysupgrade.bin")[0], "rb") as download: response = HttpResponse(download.read(), content_type="application/octet-stream") response['Content-Disposition'] = 'inline; filename=' + os.path.basename(device.serial + ".bin") os.system("rm -rf " + SRCDIR + "/files/") os.system("rm " + SRCDIR + "/bin/targets/ar71xx/generic/*") return response def rebootdevice(request, device_id): if request.user.is_authenticated: device = None for organization in Organization.objects.filter(users=request.user): device = device or Device.objects.filter(id=device_id, organization=organization) if not device: return redirect("/") device[0].reboot = True device[0].save() return redirect("/") def deletedevice(request, device_id): if request.user.is_superuser: device = get_object_or_404(Device, id=device_id) device.delete() return redirect("/") def makedevice(request): CADIR = "/etc/openvpn/ca/" CONFIGDIR = "/etc/openvpn/client-configs/" BEFORE = os.getcwd() device_serial = request.POST.get("serial", "") device_name = request.POST.get("name", "") device_organization = request.POST.get("organization", "") if not request.user.is_superuser: return redirect("/") if not device_serial: orga = Organization.objects.all() return render(request, "manager/add.html", { "title": "Add Device", "organizations": orga, } ) if glob.glob(CADIR + "/keys/" + device_serial + "*"): return HttpResponse("This key already exists.") os.chdir(CADIR) if subprocess.call(CADIR + "/generate-key " + device_serial, shell=True): return HttpResponse("Something went wrong trying to generate the key.") if glob.glob(CONFIGDIR + "/files/" + device_serial + "*"): return HttpResponse("This configuration file already exists.") os.chdir(CONFIGDIR) if subprocess.call(CONFIGDIR + "/make_config " + device_serial, shell=True): return HttpResponse("Something went wrong trying to generate the config file.") os.chdir(BEFORE) device = Device.objects.create( serial=device_serial, name=device_name, network=Network.objects.filter(intip="No VPN")[0], organization=Organization.objects.filter(id=device_organization)[0], vpnconfig = open(CONFIGDIR + "/files/" + device_serial + ".ovpn").read() ) return redirect("/")