Finish implementing initial setup process

This commit is contained in:
zontreck 2024-05-15 15:53:13 -07:00
parent d47906e10f
commit 7c358d48e0
9 changed files with 340 additions and 41 deletions

View file

@ -7,8 +7,9 @@ class Constants {
static const TITLEBAR_COLOR = Color.fromARGB(255, 97, 0, 0);
static const DRAWER_COLOR = Color.fromARGB(148, 0, 97, 97);
static const VERSION = "1.0.051524.1345";
static const VERSION = "1.0.051524.1458";
static const COPYRIGHT = "Copyright 2024 - Tara Piccari. All rights Reserved";
static const CLIENTPSK = "";
static const SERVICES_JSON =
"https://raw.githubusercontent.com/AriasCreations/AriasCreations/main/services.json";

166
lib/Packets.dart Normal file
View file

@ -0,0 +1,166 @@
import 'dart:convert';
import 'Settings.dart';
abstract class IPacket {
String encode();
HTTPMethod method();
String getType();
}
class S2CSimpleReplyPacket implements IPacket {
final bool done;
S2CSimpleReplyPacket({required this.done});
static S2CSimpleReplyPacket decode(String params) {
var map = json.decode(params);
return S2CSimpleReplyPacket(done: map['done'] as bool);
}
@override
String encode() {
return json.encode({"done": done});
}
@override
HTTPMethod method() {
return HTTPMethod.Get;
}
@override
String getType() {
return "S2CSimpleReply";
}
}
class C2SPerformSetupPacket implements IPacket {
final String PSK;
final String ClientPSK;
final String host;
final String user;
final String pass;
final String db;
C2SPerformSetupPacket(
{required this.PSK,
required this.ClientPSK,
required this.host,
required this.user,
required this.pass,
required this.db});
@override
String encode() {
return json.encode({
"psk": PSK,
"client": ClientPSK,
"host": host,
"user": user,
"pass": pass,
"db": db,
"type": getType()
});
}
static C2SPerformSetupPacket decode(String params) {
var map = json.decode(params);
return C2SPerformSetupPacket(
PSK: map['psk'] as String,
ClientPSK: map['client'] as String,
host: map['host'] as String,
user: map['user'] as String,
pass: map['pass'] as String,
db: map['db'] as String);
}
@override
HTTPMethod method() {
return HTTPMethod.Post;
}
@override
String getType() {
return "C2SPerformSetup";
}
}
class S2CPongPacket implements IPacket {
final String PSK;
final bool authorized;
S2CPongPacket({required this.PSK, required this.authorized});
@override
String encode() {
return json
.encode({"psk": PSK, "autorized": authorized, "type": getType()});
}
@override
String getType() {
return "S2CPong";
}
@override
HTTPMethod method() {
return HTTPMethod.Get;
}
static S2CPongPacket decode(String params) {
var map = json.decode(params);
return S2CPongPacket(
PSK: map['psk'] as String, authorized: map['authorized'] as bool);
}
}
class NullPacket implements IPacket {
NullPacket();
@override
String encode() {
return json.encode({});
}
static NullPacket decode(String params) {
return NullPacket();
}
@override
String getType() {
return "NullPacket";
}
@override
HTTPMethod method() {
return HTTPMethod.Get;
}
}
class C2SPingPacket implements IPacket {
final String client;
C2SPingPacket({required this.client});
@override
HTTPMethod method() {
return HTTPMethod.Post;
}
@override
String getType() {
return "C2SPing";
}
static C2SPingPacket decode(String params) {
var map = json.decode(params);
return C2SPingPacket(client: map['client'] as String);
}
@override
String encode() {
return json.encode({"client": client});
}
}

View file

@ -1,9 +1,14 @@
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:libac_flutter/nbt/impl/CompoundTag.dart';
import 'package:libac_flutter/utils/Hashing.dart';
import 'package:zontreck/Packets.dart';
enum APIEndpoint {
SetupCheck(script: "SetupCheck.php", path: "/ac/home/supports/"),
Ping(script: "Ping.php", path: "/ac/home/supports/"),
Setup(script: "Setup.php", path: "/ac/home/supports/"),
Login(script: "Login.php", path: "/ac/home/supports/");
final String script;
@ -16,6 +21,8 @@ enum APIEndpoint {
}
}
enum HTTPMethod { Get, Post, Put, Delete }
class Settings {
static Settings? _inst = null;
Settings._() {}
@ -41,6 +48,8 @@ class Settings {
String API_SERVER = "";
bool OpenSimSetupCompleted = false;
String PSK =
""; // This is not saved anywhere it is discarded when the application is unloaded.
void setServices(Map<String, dynamic> js) {
var protocol = js['api']['protocol'] as String;
@ -60,11 +69,59 @@ class Settings {
return hash;
}
Future<String> createClientPSK(String hashedPSK) async {
String hash = Hashing.sha256Hash("AriasCreations");
for (int i = 0; i < 8192; i++) {
hash = Hashing.sha256Hash("${hash}:${hashedPSK}");
Future<String> createDerivedPSK(String hashedPSK, String purpose) async {
String hash = await hashPSK("${hashedPSK}:${purpose}");
return await hashPSK("${hash}:${hashedPSK}:${purpose}"); // The derived PSK
}
Future<IPacket> sendPacketToEndpoint(
APIEndpoint endpoint, IPacket packet) async {
Response<dynamic> reply;
switch (packet.method()) {
case HTTPMethod.Post:
{
reply = await dio.post(endpoint.getURL(), data: packet.encode());
break;
}
case HTTPMethod.Get:
{
reply = await dio.get(endpoint.getURL());
break;
}
case HTTPMethod.Delete:
{
reply = await dio.delete(endpoint.getURL(), data: packet.encode());
break;
}
case HTTPMethod.Put:
{
reply = await dio.put(endpoint.getURL(), data: packet.encode());
break;
}
}
return processResponsePacket(reply.data as String);
}
Future<IPacket> processResponsePacket(String reply) async {
var tmpMap = json.decode(reply);
String packetType = tmpMap['type'] as String;
switch (packetType) {
case "S2CSimpleReply":
{
S2CSimpleReplyPacket response = S2CSimpleReplyPacket.decode(reply);
return response;
}
case "S2CPong":
{
S2CPongPacket pong = S2CPongPacket.decode(reply);
return pong;
}
default:
{
return NullPacket();
}
}
return Hashing.sha256Hash(hash);
}
}

View file

@ -1,9 +1,8 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:footer/footer.dart';
import 'package:footer/footer_view.dart';
import 'package:zontreck/Constants.dart';
import 'package:zontreck/Packets.dart';
import 'package:zontreck/Settings.dart';
class OpenSimPage extends StatefulWidget {
@ -26,15 +25,18 @@ class OpenSimPageState extends State<OpenSimPage> {
@override
Future<void> didChangeDependencies() async {
// Send check for setup completion
var reply = await settings.dio.get(APIEndpoint.SetupCheck.getURL());
var reply = await settings.sendPacketToEndpoint(
APIEndpoint.SetupCheck, NullPacket());
var simpleReply = reply as S2CSimpleReplyPacket;
if (simpleReply.done) {
settings.OpenSimSetupCompleted = true;
} else
settings.OpenSimSetupCompleted = false;
var replyJson = json.decode(reply.data);
if (replyJson['done'] as bool == true) {
setState(() {
settings.OpenSimSetupCompleted = true;
});
}
var pong =
await settings.sendPacketToEndpoint(APIEndpoint.Ping, NullPacket());
setState(() {});
}
@override
@ -61,6 +63,8 @@ class OpenSimPageState extends State<OpenSimPage> {
children: [
ListTile(
title: Text("Initial Setup Required"),
subtitle: Text(
"Please use the same database/user as robust's database\n\nNOTE: Only MySQL/MariaDB is supported by this interface"),
tileColor: Constants.TITLEBAR_COLOR,
),
ListTile(
@ -96,29 +100,48 @@ class OpenSimPageState extends State<OpenSimPage> {
controller: databaseNameController,
),
),
ListTile(
title: Text(
"For the PreShared Secret, please enter any text you wish. This is hashed 8192 times for the server key. And an additional 16384 times for the client, and any derived key thereafter"),
tileColor: Constants.TITLEBAR_COLOR,
),
ListTile(
title: Text("PreShared Secret"),
subtitle: TextField(
controller: PSKController,
decoration: InputDecoration(
hintText:
"Pre-Shared Key. Long text that gets hashed"),
"Pre-Shared Key. Some text that gets hashed several thousand times to create a server and client key"),
),
),
ListTile(
title: Text("PSK: ${PSKHash}"),
subtitle: Text("Client: ${clientPSK}"),
),
ElevatedButton(
onPressed: () async {
var PSK =
PSKHash =
await settings.hashPSK(PSKController.text);
clientPSK = await settings.createClientPSK(PSK);
clientPSK = await settings.createDerivedPSK(
PSKHash, "client");
setState(() {
PSKHash = PSK;
});
C2SPerformSetupPacket packet =
C2SPerformSetupPacket(
PSK: PSKHash,
ClientPSK: clientPSK,
host: databaseHostController.text,
user: databaseUsernameController.text,
pass: databasePasswordController.text,
db: databaseHostController.text);
var responsePacket =
await settings.sendPacketToEndpoint(
APIEndpoint.Setup, packet)
as S2CSimpleReplyPacket;
if (responsePacket.done) {
settings.OpenSimSetupCompleted = true;
} else
settings.OpenSimSetupCompleted = false;
setState(() {});
},
child: Text("Submit"))
],

View file

@ -26,6 +26,16 @@ function rewrite_DB_conf($host, $user, $pass, $db)
file_put_contents("../database.user.php", $ptl);
}
function rewriteSystemInclude($psk, $clientPSK)
{
$ptl = "<\?php\n"
. "define(\"PSK\", \"$psk\");\n"
. "define(\"CLIENTPSK\", \"$clientPSK\");\n"
. "\?>";
file_put_contents("../system.user.php", $ptl);
}
if(file_exists("../database.user.php"))
require("../database.user.php");
else
@ -33,8 +43,6 @@ else
if(file_exists("../system.user.php"))
require("../system.user.php");
else
require("System.php");
session_start();

31
php/Ping.php Normal file
View file

@ -0,0 +1,31 @@
<?php
if(!defined("COMMON"))
require("Common.php");
$js = getJsonizedInput();
$psk = "";
$allow=false;
if(!defined("CLIENTPSK")) {
$allow=true;
} else {
if($js['client'] == CLIENTPSK) {
// Authorized. Send the PSK value to the client
$allow=true;
$psk = PSK;
}else {
$allow=false;
}
}
$ret = array(
"type" => "S2CPong",
"authorized" => $allow,
"psk" => $psk
);
die(json_encode($ret));
?>

View file

@ -4,11 +4,28 @@ if(!defined("COMMON"))
$js = getJsonizedInput();
$host = $js['host'];
$user = $js['user'];
$pass = $js['pass'];
$db = $js['db'];
if(!defined("PSK") || PSK == $js['psk']) {
rewrite_DB_conf($host, $user, $pass, $db);
$host = $js['host'];
$user = $js['user'];
$pass = $js['pass'];
$db = $js['db'];
$psk = $js['psk'];
$clientPsk = $js['client'];
rewrite_DB_conf($host, $user, $pass, $db);
rewriteSystemInclude($psk, $clientPsk);
die(json_encode(array(
"done" => true,
"type" => "S2CSimpleReply"
)));
}
die(json_encode(array(
"done" => false,
"type" => "S2CSimpleReply"
)));
?>

View file

@ -5,13 +5,15 @@ if(!defined("COMMON"))
if(DB_NAME == "changeme" && DB_PASS == "changeme") {
$ret = array (
"done" => false
"done" => false,
"type" => "S2CSimpleReply"
);
header("X-Zontreck-Setup-Completed", "FALSE");
die(json_encode($ret));
}else {
$ret = array (
"done" => true
"done" => true,
"type" => "S2CSimpleReply"
);
header("X-Zontreck-Setup-Completed", "TRUE");
die(json_encode($ret));

View file

@ -1,6 +0,0 @@
<?php
define("PSK", "No PSK Set");
define("ClientPSK", "No Client PSK Set");
?>