Skip to content

Commit

Permalink
Handle superaccess requests in separate process & implement plugin si…
Browse files Browse the repository at this point in the history
…gning and authority verifying
  • Loading branch information
serivesmejia committed Oct 28, 2024
1 parent 2ea9305 commit c195227
Show file tree
Hide file tree
Showing 19 changed files with 1,505 additions and 325 deletions.

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion EOCV-Sim/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ dependencies {
implementation "org.slf4j:slf4j-api:$slf4j_version"
implementation "org.apache.logging.log4j:log4j-api:$log4j_version"
implementation "org.apache.logging.log4j:log4j-core:$log4j_version"
implementation "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
implementation "org.apache.logging.log4j:log4j-slf4j2-impl:$log4j_version"

implementation "com.github.deltacv:steve:1.1.1"
api("com.github.deltacv:AprilTagDesktop:$apriltag_plugin_version") {
Expand All @@ -87,6 +87,8 @@ dependencies {
implementation 'com.formdev:flatlaf-intellij-themes:3.5.1'
implementation 'com.miglayout:miglayout-swing:11.4.2'

implementation("org.java-websocket:Java-WebSocket:1.5.2")

implementation 'net.lingala.zip4j:zip4j:2.11.3'

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinx_coroutines_version"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import com.github.serivesmejia.eocvsim.util.FileFilters
import com.github.serivesmejia.eocvsim.util.JavaProcess
import com.github.serivesmejia.eocvsim.util.SysUtil
import com.github.serivesmejia.eocvsim.util.event.EventHandler
import com.github.serivesmejia.eocvsim.util.exception.MaxActiveContextsException
import com.github.serivesmejia.eocvsim.util.exception.handling.CrashReport
import com.github.serivesmejia.eocvsim.util.exception.handling.EOCVSimUncaughtExceptionHandler
import com.github.serivesmejia.eocvsim.util.fps.FpsLimiter
Expand All @@ -50,6 +49,7 @@ import com.qualcomm.robotcore.eventloop.opmode.OpMode
import com.qualcomm.robotcore.eventloop.opmode.OpModePipelineHandler
import io.github.deltacv.common.pipeline.util.PipelineStatisticsCalculator
import io.github.deltacv.common.util.ParsedVersion
import io.github.deltacv.eocvsim.plugin.security.AuthorityFetcher
import io.github.deltacv.eocvsim.plugin.loader.PluginManager
import io.github.deltacv.vision.external.PipelineRenderHook
import nu.pattern.OpenCV
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class PluginOutput(
) : Appendable {

companion object {
private const val SPECIAL = "[13mck]"
const val SPECIAL = "[13mck]"

const val SPECIAL_OPEN = "$SPECIAL[OPEN]"
const val SPECIAL_OPEN_MGR = "$SPECIAL[OPEN_MGR]"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,19 @@ public static int exec(Class klass, List<String> jvmArgs, List<String> args) thr
return execClasspath(klass, null, System.getProperty("java.class.path"), jvmArgs, args);
}

/**
* Executes a Java process with the given class and arguments.
* @param klass the class to execute
* @param ioReceiver the receiver for the process' input and error streams (will use inheritIO if null)
* @param jvmArgs the JVM arguments to pass to the process
* @param args the arguments to pass to the class
* @return the exit value of the process
* @throws InterruptedException if the process is interrupted
* @throws IOException if an I/O error occurs
*/
public static int exec(Class klass, ProcessIOReceiver ioReceiver, List<String> jvmArgs, List<String> args) throws InterruptedException, IOException {
return execClasspath(klass, ioReceiver, System.getProperty("java.class.path"), jvmArgs, args);
}


}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.github.serivesmejia.eocvsim.util.extension

import com.github.serivesmejia.eocvsim.util.SysUtil
import java.security.MessageDigest

/**
* Remove a string from the end of this string
* @param rem the string to remove
Expand All @@ -12,4 +15,10 @@ fun String.removeFromEnd(rem: String): String {
return trim()
}

val Any.hexString get() = Integer.toHexString(hashCode())!!
val Any.hashString get() = Integer.toHexString(hashCode())!!

val String.hashString: String get() {
val messageDigest = MessageDigest.getInstance("SHA-256")
val hash = messageDigest.digest(toByteArray())
return SysUtil.byteArray2Hex(hash)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2024 Sebastian Erives
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/

package com.github.serivesmejia.eocvsim.util.serialization

import com.google.gson.*
import java.lang.reflect.Type

private val gson = Gson()

open class PolymorphicAdapter<T>(val name: String) : JsonSerializer<T>, JsonDeserializer<T> {

override fun serialize(src: T, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
val obj = JsonObject()

obj.addProperty("${name}Class", src!!::class.java.name)
obj.add(name, gson.toJsonTree(src))

return obj
}

@Suppress("UNCHECKED_CAST")
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): T {
val className = json.asJsonObject.get("${name}Class").asString
val clazz = Class.forName(className)

return gson.fromJson(json.asJsonObject.get(name), clazz) as T
}

}
Original file line number Diff line number Diff line change
@@ -1,34 +1,32 @@
/*
* Copyright (c) 2024 Sebastian Erives
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/

package io.github.deltacv.eocvsim.gui.dialog;

import javax.swing.*;

public class SuperAccessRequestMain {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new SuperAccessRequest(args[0].replace("-", " "), args[1].replace("-", " "));
});
}
}
/*
* Copyright (c) 2024 Sebastian Erives
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/

package io.github.deltacv.eocvsim.gui.dialog;

import javax.swing.*;

public class SuperAccessRequestMain {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new SuperAccessRequest(args[0].replace("-", " "), args[1].replace("-", " ")));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ import com.github.serivesmejia.eocvsim.gui.dialog.AppendDelegate
import com.github.serivesmejia.eocvsim.gui.dialog.PluginOutput
import com.github.serivesmejia.eocvsim.util.SysUtil
import com.github.serivesmejia.eocvsim.util.event.EventHandler
import com.github.serivesmejia.eocvsim.util.extension.hashString
import com.github.serivesmejia.eocvsim.util.extension.plus
import com.github.serivesmejia.eocvsim.util.loggerForThis
import com.moandjiezana.toml.Toml
import io.github.deltacv.common.util.ParsedVersion
import io.github.deltacv.eocvsim.plugin.EOCVSimPlugin
import io.github.deltacv.eocvsim.plugin.security.PluginSignature
import io.github.deltacv.eocvsim.plugin.security.PluginSignatureVerifier
import io.github.deltacv.eocvsim.sandbox.nio.SandboxFileSystem
import net.lingala.zip4j.ZipFile
import java.io.File
Expand All @@ -44,6 +47,24 @@ enum class PluginSource {
FILE
}

class PluginParser(pluginToml: Toml) {
val pluginName = pluginToml.getString("name") ?: throw InvalidPluginException("No name in plugin.toml")
val pluginVersion = pluginToml.getString("version") ?: throw InvalidPluginException("No version in plugin.toml")

val pluginAuthor = pluginToml.getString("author") ?: throw InvalidPluginException("No author in plugin.toml")
val pluginAuthorEmail = pluginToml.getString("author-email", "")

val pluginMain = pluginToml.getString("main") ?: throw InvalidPluginException("No main in plugin.toml")

val pluginDescription = pluginToml.getString("description", "")

/**
* Get the hash of the plugin based off the plugin name and author
* @return the hash
*/
fun hash() = "${pluginName}${PluginOutput.SPECIAL}${pluginAuthor}".hashString
}

/**
* Loads a plugin from a jar file
* @param pluginFile the jar file of the plugin
Expand Down Expand Up @@ -103,13 +124,18 @@ class PluginLoader(
lateinit var fileSystem: SandboxFileSystem
private set

/**
* The signature of the plugin, issued by a verified authority
*/
val signature by lazy { PluginSignatureVerifier.verify(pluginFile) }

val fileSystemZip by lazy { PluginManager.FILESYSTEMS_FOLDER + File.separator + "${hash()}-fs" }
val fileSystemZipPath by lazy { fileSystemZip.toPath() }

/**
* Whether the plugin has super access (full system access)
*/
val hasSuperAccess get() = eocvSim.config.superAccessPluginHashes.contains(pluginFileHash)
val hasSuperAccess get() = eocvSim.pluginManager.superAccessDaemonClient.checkAccess(pluginFile)

init {
pluginClassLoader = PluginClassLoader(
Expand All @@ -131,13 +157,13 @@ class PluginLoader(
?: throw InvalidPluginException("No plugin.toml in the jar file")
)

pluginName = pluginToml.getString("name") ?: throw InvalidPluginException("No name in plugin.toml")
pluginVersion = pluginToml.getString("version") ?: throw InvalidPluginException("No version in plugin.toml")
val parser = PluginParser(pluginToml)

pluginDescription = pluginToml.getString("description", "")

pluginAuthor = pluginToml.getString("author") ?: throw InvalidPluginException("No author in plugin.toml")
pluginAuthorEmail = pluginToml.getString("author-email", "")
pluginName = parser.pluginName
pluginVersion = parser.pluginVersion
pluginAuthor = parser.pluginAuthor
pluginAuthorEmail = parser.pluginAuthorEmail
pluginDescription = parser.pluginDescription
}

/**
Expand Down Expand Up @@ -258,19 +284,14 @@ class PluginLoader(
* @param reason the reason for requesting super access
*/
fun requestSuperAccess(reason: String): Boolean {
if(hasSuperAccess) return true
return eocvSim.pluginManager.requestSuperAccessFor(this, reason)
}

/**
* Get the hash of the plugin file based off the plugin name and author
* Get the hash of the plugin based off the plugin name and author
* @return the hash
*/
fun hash(): String {
val messageDigest = MessageDigest.getInstance("SHA-256")
messageDigest.update("${pluginName} by ${pluginAuthor}".toByteArray())
return SysUtil.byteArray2Hex(messageDigest.digest())
}
fun hash() = "${pluginName}${PluginOutput.SPECIAL}${pluginAuthor}".hashString

/**
* Get the hash of the plugin file based off the file contents
Expand Down
Loading

0 comments on commit c195227

Please sign in to comment.