commit c4c05b428811fc16c1e17a81448d79ea003ce832 Author: xenia Date: Sun Apr 7 18:14:00 2024 -0400 add ghidra server module diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..c4d1b73 --- /dev/null +++ b/default.nix @@ -0,0 +1,13 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ + ./modules/ghidra-server + ]; + + # nixpkgs.overlays = [ + # (final: prev: { + # + # }) + # ]; +} diff --git a/modules/ghidra-server/custom.log4j.xml b/modules/ghidra-server/custom.log4j.xml new file mode 100644 index 0000000..5e92937 --- /dev/null +++ b/modules/ghidra-server/custom.log4j.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/ghidra-server/default.nix b/modules/ghidra-server/default.nix new file mode 100644 index 0000000..3da9112 --- /dev/null +++ b/modules/ghidra-server/default.nix @@ -0,0 +1,78 @@ +{ config, lib, pkgs, ... }: +with lib; +let cfg = config.services.ghidra-server; in { + options.services.ghidra-server = { + enable = mkEnableOption "ghidra-server"; + enableAdminCli = mkEnableOption "ghidra-svrAdmin"; + package = mkPackageOption pkgs "ghidra" { }; + jdkPackage = mkPackageOption pkgs "openjdk17" { }; + host = mkOption { + default = null; + defaultText = literalExpression "null"; + example = literalExpression "\"myserver.lol\""; + description = "Ghidra server hostname or IP."; + type = types.str; + }; + basePort = mkOption { + default = 13100; + description = mdDoc "Ghidra server base port - the server will use 3 consecutive TCP ports starting from the provided port number."; + type = types.port; + }; + directory = mkOption { + default = "/var/lib/ghidra-server"; + description = mdDoc "Directory for Ghidra server data."; + type = types.str; + }; + user = mkOption { + type = types.str; + default = "ghidra"; + description = mdDoc "User account under which ghidra server runs."; + }; + group = mkOption { + type = types.str; + default = "ghidra"; + description = mdDoc "Group account under which ghidra server runs."; + }; + }; + + config = mkIf cfg.enable { + users.users."${cfg.user}" = { + isSystemUser = true; + home = cfg.directory; + group = cfg.group; + createHome = true; + packages = [ cfg.package cfg.jdkPackage ]; + }; + + users.groups."${cfg.group}" = {}; + + systemd.services."ghidra-server" = + let + ghidra_log4j_config = ./custom.log4j.xml; + ghidra_java_opt = "-Dlog4j.configurationFile=${ghidra_log4j_config} -Djava.net.preferIPv4Stack=true -Djava.io.tmpdir=/tmp -Djna.tmpdir=/tmp -Dghidra.tls.server.protocols=TLSv1.2;TLSv1.3 -Ddb.buffers.DataBuffer.compressedOutput=true -Xms396m -Xmx768m"; + ghidra_home = "${cfg.package}/lib/ghidra"; + ghidra_classpath = with builtins; let + input = lib.readFile "${ghidra_home}/Ghidra/Features/GhidraServer/data/classpath.frag"; + inputSplit = split "[^\n]*ghidra_home.([^\n]*)\n" input; + paths = map head (filter isList inputSplit); + in ghidra_home + (concatStringsSep (":" + ghidra_home) paths); + ghidra_mainclass = "ghidra.server.remote.GhidraServer"; + ghidra_args = "-a0 -u -p${toString cfg.basePort} -ip ${cfg.host} ${cfg.directory}/repositories"; + in { + description = "Ghidra server"; + after = ["network.target"]; + serviceConfig = { + ExecStart = "${cfg.jdkPackage}/bin/java ${ghidra_java_opt} -classpath ${ghidra_classpath} ${ghidra_mainclass} ${ghidra_args}"; + WorkingDirectory = cfg.directory; + Environment = "GHIDRA_HOME=${ghidra_home}"; + User = cfg.user; + Group = cfg.group; + SuccessExitStatus = 143; + + PrivateTmp = true; + NoNewPrivileges = true; + }; + wantedBy = ["multi-user.target"]; + }; + }; +}