forked from zer.ooo/web
[wip]
parent
23c3cf530e
commit
ebddf2f031
@ -1,7 +1,10 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
BINDIR=$(dirname $(realpath $0));
|
|
||||||
BASEDIR=$(realpath "$BINDIR/../");
|
set -e;
|
||||||
cd $BASEDIR;
|
|
||||||
|
BINDIR="$(dirname $(realpath "${0}"))";
|
||||||
|
BASEDIR="$(realpath "${BINDIR}/../")";
|
||||||
|
cd "${BASEDIR}";
|
||||||
rm -rf ./storage/ca/*;
|
rm -rf ./storage/ca/*;
|
||||||
mkdir ./storage/ca/certs;
|
mkdir ./storage/ca/certs;
|
||||||
touch ./storage/ca/{,certs/}.gitkeep;
|
touch ./storage/ca/certs/.gitkeep ./storage/ca/.gitkeep;
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e;
|
||||||
|
|
||||||
BASEDIR="$(dirname $(realpath $0))/../";
|
BASEDIR="$(dirname $(realpath $0))/../";
|
||||||
cd $BASEDIR;
|
cd "${BASEDIR}";
|
||||||
STORAGE=$(realpath "$BASEDIR/storage/ca");
|
STORAGE="$(realpath "${BASEDIR}/storage/ca")";
|
||||||
|
|
||||||
mkdir -p $STORAGE;
|
mkdir -p "${STORAGE}/certs";
|
||||||
mkdir -p $STORAGE/certs;
|
|
||||||
|
|
||||||
echo 01 > $STORAGE/serial;
|
echo 01 > "${STORAGE}/serial";
|
||||||
echo 01 > $STORAGE/crl_serial;
|
echo 01 > "${STORAGE}/crl_serial";
|
||||||
touch $STORAGE/database;
|
touch "${STORAGE}/database";
|
||||||
touch $STORAGE/database.attr;
|
touch "${STORAGE}/database.attr";
|
||||||
|
|
||||||
$BASEDIR/bin/create-ca $1;
|
"${BASEDIR}/bin/create-ca" $1;
|
||||||
$BASEDIR/bin/create-crl;
|
"${BASEDIR}/bin/create-crl";
|
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Created by PhpStorm.
|
||||||
|
* User: eater
|
||||||
|
* Date: 6/6/16
|
||||||
|
* Time: 11:28 PM
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Eater\Glim\Handler;
|
||||||
|
|
||||||
|
|
||||||
|
class CRL extends Main
|
||||||
|
{
|
||||||
|
function handle()
|
||||||
|
{
|
||||||
|
return $this->getResponse()
|
||||||
|
->withHeader('Content-Type', 'plain/text')
|
||||||
|
->withHeader('Content-Disposition', 'attachment; filename="crl.pem"')
|
||||||
|
->write(file_get_contents($this->getCore()->getBaseDir() . '/storage/ca/crl.pem'));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Eater\Glim\Handler\Install;
|
||||||
|
|
||||||
|
use Eater\Glim\Service\User;
|
||||||
|
|
||||||
|
class Action extends Show
|
||||||
|
{
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
/** @var User $user */
|
||||||
|
$user = $this->get('user');
|
||||||
|
|
||||||
|
$caCN = $this->post('ca-cn');
|
||||||
|
|
||||||
|
/* @var \Aura\Session\Session $session */
|
||||||
|
$session = $this->get('session');
|
||||||
|
$segment = $session->getSegment('main');
|
||||||
|
|
||||||
|
if (trim($caCN) === "") {
|
||||||
|
$segment->setFlash('error', 'CA Common name can\'t be empty');
|
||||||
|
return $this->redirect('/install');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var \Twig_Environment $twig */
|
||||||
|
$twig = $this->get('twig');
|
||||||
|
|
||||||
|
$opensslConf = $twig->render('etc/openssl-ca.conf.twig', [
|
||||||
|
'host' => $this->post('domainWithPort')
|
||||||
|
]);
|
||||||
|
|
||||||
|
file_put_contents($this->getCore()->getBaseDir() . '/etc/openssl.conf', $opensslConf);
|
||||||
|
|
||||||
|
exec($this->getCore()->getBaseDir() . '/bin/clean-all');
|
||||||
|
exec($this->getCore()->getBaseDir() . '/bin/setup ' . escapeshellarg($caCN));
|
||||||
|
|
||||||
|
$newUser = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$newUser = $user->createSuperuser($this->post('username'), $this->post('password'));
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$segment->setFlash("error", $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($newUser === null) {
|
||||||
|
return $this->redirect('/install');
|
||||||
|
}
|
||||||
|
|
||||||
|
$segment->set('user', $newUser);
|
||||||
|
|
||||||
|
return $this->redirect('/panel');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Eater\Glim\Handler\Install;
|
||||||
|
|
||||||
|
use Eater\Glim\Handler\Main;
|
||||||
|
use Eater\Glim\Model\UserQuery;
|
||||||
|
|
||||||
|
class Show extends Main
|
||||||
|
{
|
||||||
|
public function beforeHandle() {
|
||||||
|
if (UserQuery::create()->findOne()) {
|
||||||
|
return $this->redirect('/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$return = 1;
|
||||||
|
$execEnabled = $this->isExecEnabled();
|
||||||
|
$hasOpenSsl = false;
|
||||||
|
if ($execEnabled) {
|
||||||
|
exec('command -v openssl', $output, $return);
|
||||||
|
$hasOpenSsl = $return === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'hasExecEnabled' => $execEnabled,
|
||||||
|
'hasOpenSsl' => $hasOpenSsl,
|
||||||
|
'hasOpenSslExtension' => extension_loaded('openssl'),
|
||||||
|
'hasZipExtension' => extension_loaded('zip'),
|
||||||
|
'hostname' => parse_url($_SERVER['HTTP_HOST'], PHP_URL_HOST),
|
||||||
|
'hostnameWithPort' => $_SERVER['HTTP_HOST']
|
||||||
|
];
|
||||||
|
|
||||||
|
return $this->render('install.html.twig', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isExecEnabled() {
|
||||||
|
if (ini_get('safe_mode')) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$d = ini_get('disable_functions');
|
||||||
|
$s = ini_get('suhosin.executor.func.blacklist');
|
||||||
|
if ("$d$s") {
|
||||||
|
$array = preg_split('/,\s*/', "$d,$s");
|
||||||
|
if (in_array('exec', $array)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Created by PhpStorm.
|
||||||
|
* User: eater
|
||||||
|
* Date: 6/12/16
|
||||||
|
* Time: 3:26 PM
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Eater\Glim\Handler\Panel\Servers;
|
||||||
|
|
||||||
|
|
||||||
|
use Eater\Glim\Handler\Session;
|
||||||
|
use Eater\Glim\Model\Certificate;
|
||||||
|
use Eater\Glim\Model\CertificateQuery;
|
||||||
|
use Eater\Glim\Model\Server;
|
||||||
|
use Eater\Glim\Model\ServerQuery;
|
||||||
|
|
||||||
|
class Config extends Session
|
||||||
|
{
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$zipFile = tempnam(sys_get_temp_dir(), '0zip');
|
||||||
|
$zip = new \ZipArchive();
|
||||||
|
$zip->open($zipFile, \ZipArchive::CREATE);
|
||||||
|
$server = ServerQuery::create()->findOneByFingerprint($this->attr('fingerprint'));
|
||||||
|
$name = $server->getFqdn();
|
||||||
|
|
||||||
|
$this->fillZipWithCaAndConfig($zip, $server);
|
||||||
|
|
||||||
|
$cert = $this->attr('cert');
|
||||||
|
|
||||||
|
if ($cert !== null) {
|
||||||
|
$certModel = CertificateQuery::create()->findOneByUserAndName($this->getUser(), $cert);
|
||||||
|
$this->addClientCertificateData($zip, $certModel);
|
||||||
|
|
||||||
|
$name .= '-' . $certModel->getName() . '.' . $certModel->getSerial();
|
||||||
|
}
|
||||||
|
|
||||||
|
$zip->close();
|
||||||
|
|
||||||
|
$zipContents = file_get_contents($zipFile);
|
||||||
|
unlink($zipFile);
|
||||||
|
|
||||||
|
return $this->getResponse()
|
||||||
|
->withHeader('Content-Type', 'application/zip')
|
||||||
|
->withHeader('Content-Disposition', 'attachment; filename="' . $name . '.zip"')
|
||||||
|
->write($zipContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \ZipArchive $zip
|
||||||
|
* @param Server $server
|
||||||
|
*/
|
||||||
|
public function fillZipWithCaAndConfig($zip, $server)
|
||||||
|
{
|
||||||
|
$config = $this->getConfigForServerFingerprint($server);
|
||||||
|
$zip->addFromString('server.conf', $config);
|
||||||
|
$zip->addFromString('ca.crt', file_get_contents($this->getCore()->getBaseDir() . '/storage/ca/ca.crt'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Server $server
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getConfigForServerFingerprint($server)
|
||||||
|
{
|
||||||
|
/** @var \Twig_Environment $twig */
|
||||||
|
$twig = $this->get('twig');
|
||||||
|
|
||||||
|
$config = $twig->render('etc/openvpn-client.conf.twig', [
|
||||||
|
'server' => $server
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \ZipArchive $zip
|
||||||
|
* @param Certificate $cert
|
||||||
|
*/
|
||||||
|
public function addClientCertificateData($zip, $cert)
|
||||||
|
{
|
||||||
|
$zip->addFromString('client.crt', $cert->getCertificate());
|
||||||
|
|
||||||
|
if ($cert->hasPrivateKey()) {
|
||||||
|
$zip->addFromString('client.key', $cert->getPrivateKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Eater\Glim\Handler\Panel\Servers;
|
||||||
|
|
||||||
|
use Eater\Glim\Handler\Session;
|
||||||
|
use Eater\Glim\Model\ServerQuery;
|
||||||
|
use Eater\Glim\Service\CA;
|
||||||
|
use Eater\Glim\Service\Server;
|
||||||
|
use Symfony\Component\Config\Definition\Exception\Exception;
|
||||||
|
|
||||||
|
class Remove extends Session
|
||||||
|
{
|
||||||
|
protected $shouldHaveSuperuser = true;
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$server = ServerQuery::create()->findOneByFingerprint($this->post('fingerprint'));
|
||||||
|
$server->delete();
|
||||||
|
|
||||||
|
return $this->json([
|
||||||
|
'success' => true
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
client
|
||||||
|
|
||||||
|
dev zerooo
|
||||||
|
dev-type tun
|
||||||
|
|
||||||
|
proto {{ server.getProtocol() }}
|
||||||
|
|
||||||
|
remote {{ server.getExternalIp() }} {{ server.getPort() }}
|
||||||
|
resolv-retry infinite
|
||||||
|
nobind
|
||||||
|
|
||||||
|
user nobody
|
||||||
|
group nogroup
|
||||||
|
|
||||||
|
persist-key
|
||||||
|
persist-tun
|
||||||
|
|
||||||
|
ca ca.crt
|
||||||
|
cert client.crt
|
||||||
|
key client.key
|
||||||
|
|
||||||
|
remote-cert-tls server
|
||||||
|
|
||||||
|
cipher BF-CBC
|
||||||
|
|
||||||
|
comp-lzo
|
||||||
|
verb 3
|
@ -0,0 +1,32 @@
|
|||||||
|
port {{ server.getPort() }}
|
||||||
|
proto {{ server.getProtocol() }}
|
||||||
|
|
||||||
|
dev ovpn0
|
||||||
|
dev-type tun
|
||||||
|
|
||||||
|
ca ca.crt
|
||||||
|
cert server.crt
|
||||||
|
key server.key
|
||||||
|
|
||||||
|
dh dh2048.pem
|
||||||
|
|
||||||
|
server {{ server.getInternalIp() }} {{ server.getNetmaskIp() }}
|
||||||
|
|
||||||
|
ifconfig-pool-persist ipp.txt
|
||||||
|
|
||||||
|
push "redirect-gateway def1 bypass-dhcp"
|
||||||
|
|
||||||
|
push "dhcp-option DNS {{ server.getFirstDns() }}"
|
||||||
|
push "dhcp-option DNS {{ server.getSecondDns() }}"
|
||||||
|
keepalive 10 120
|
||||||
|
cipher BF-CBC
|
||||||
|
|
||||||
|
crl-verify crl.pem
|
||||||
|
|
||||||
|
comp-lzo
|
||||||
|
|
||||||
|
user nobody
|
||||||
|
group nogroup
|
||||||
|
|
||||||
|
persist-key
|
||||||
|
persist-tun
|
@ -0,0 +1,80 @@
|
|||||||
|
{% extends "base.html.twig" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="col-md-offset-3 col-md-6">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="row">
|
||||||
|
<h2>Welcome to your Zer.ooo install</h2>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h3>Checking for extensions and settings</h3>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<table class="table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{{ hasExecEnabled ? 'Yes' : 'No' }}</td>
|
||||||
|
<td>Is <kbd>exec</kbd> available?</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ hasOpenSsl ? 'Yes' : 'No' }}</td>
|
||||||
|
<td>Is the <kbd>openssl</kbd> binary available?</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ hasOpenSslExtension ? 'Yes' : 'No' }}</td>
|
||||||
|
<td>Is the openssl module loaded?</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ hasZipExtension ? 'Yes' : 'No' }}</td>
|
||||||
|
<td>Is the zip module loaded?</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if not (hasExecEnabled and hasOpenSslExtension and hasOpenSsl and hasZipExtension) %}
|
||||||
|
<div class="row">
|
||||||
|
Those functions are essential for the functionality of Zer.ooo, please enable them<br>
|
||||||
|
<br>
|
||||||
|
<a href="/install" class="btn btn-primary">Refresh</a>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="row">
|
||||||
|
<h3>Create your superuser</h3>
|
||||||
|
</div>
|
||||||
|
<form method="post" action="/install">
|
||||||
|
<div class="row">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username">Username</label>
|
||||||
|
<input id="username" class="form-control" type="text" name="username">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input id="password" class="form-control" type="password" name="password">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<h3>Server details</h3>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="ca-cn">CA Common Name</label>
|
||||||
|
<input type="text" id="ca-cn" name="ca-cn" class="form-control" value="{{ hostname }}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="domainWithPort">HTTP Host (NOT HTTPS! needed for CRL)</label>
|
||||||
|
<input type="text" id="domainWithPort" name="domainWithPort" class="form-control" value="{{ hostnameWithPort }}" />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="btn btn-primary pull-right">Finish install</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue