You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

156 lines
4.1 KiB

<?php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class Certbot {
private $mc;
private $http;
public function index(Request $request, Response $response) {
session_start();
$state = mt_rand(10000,99999);
$_SESSION['state'] = $state;
$response->setContent(p3k\XRay\view('certbot', [
'title' => 'X-Ray',
'state' => $state
]));
return $response;
}
public function start_auth(Request $request, Response $response) {
session_start();
$_SESSION['client_id'] = $request->get('client_id');
$_SESSION['redirect_uri'] = $request->get('redirect_uri');
$query = http_build_query([
'me' => $request->get('me'),
'client_id' => $request->get('client_id'),
'redirect_uri' => $request->get('redirect_uri'),
'state' => $request->get('state'),
]);
$response->headers->set('Location', 'https://indieauth.com/auth?'.$query);
$response->setStatusCode(302);
return $response;
}
public function redirect(Request $request, Response $response) {
session_start();
$this->http = new p3k\HTTP();
if(!isset($_SESSION['state']) || $_SESSION['state'] != $request->get('state')) {
$response->headers->set('Location', '/cert?error=invalid_state');
$response->setStatusCode(302);
return $response;
}
if($code = $request->get('code')) {
$res = $this->http->post('https://indieauth.com/auth', http_build_query([
'code' => $code,
'client_id' => $_SESSION['client_id'],
'redirect_uri' => $_SESSION['redirect_uri'],
'state' => $_SESSION['state']
]), [
'Accept: application/json'
]);
$verify = json_decode($res['body'], true);
unset($_SESSION['state']);
if(isset($verify['me'])) {
if(in_array($verify['me'], Config::$admins)) {
$_SESSION['me'] = $verify['me'];
$response->headers->set('Location', '/cert');
} else {
$response->headers->set('Location', '/cert?error=invalid_user');
}
} else {
$response->headers->set('Location', '/cert?error=invalid');
}
} else {
$response->headers->set('Location', '/cert?error=missing_code');
}
$response->setStatusCode(302);
return $response;
}
public function save_challenge(Request $request, Response $response) {
session_start();
if(!isset($_SESSION['me']) || !in_array($_SESSION['me'], Config::$admins)) {
$response->headers->set('Location', '/cert?error=forbidden');
$response->setStatusCode(302);
return $response;
}
$token = $request->get('token');
$challenge = $request->get('challenge');
if(preg_match('/acme-challenge\/(.+)/', $token, $match)) {
$token = $match[1];
} elseif(!preg_match('/^[_a-zA-Z0-9]+$/', $token)) {
echo "Invalid token format\n";
die();
}
$this->_mc();
$this->mc->set('acme-challenge-'.$token, json_encode([
'token' => $token,
'challenge' => $challenge
]), 0, 600);
$response->setContent(p3k\XRay\view('certbot', [
'title' => 'X-Ray',
'challenge' => $challenge,
'token' => $token,
'verified' => true
]));
return $response;
}
public function logout(Request $request, Response $response) {
session_start();
unset($_SESSION['me']);
unset($_SESSION['client_id']);
unset($_SESSION['redirect_uri']);
unset($_SESSION['state']);
session_destroy();
$response->headers->set('Location', '/cert');
$response->setStatusCode(302);
return $response;
}
public function challenge(Request $request, Response $response, array $args) {
$this->_mc();
$token = $args['token'];
if($cache = $this->mc->get('acme-challenge-'.$token)) {
$acme = json_decode($cache, true);
$response->setContent($acme['challenge']);
} else {
$response->setStatusCode(404);
$response->setContent("Not Found\n");
}
$response->headers->set('Content-Type', 'text/plain');
return $response;
}
private function _mc() {
$this->mc = new Memcache();
$this->mc->addServer('127.0.0.1');
}
}