diff --git a/build.zig b/build.zig index 209a2ff..5efafbc 100644 --- a/build.zig +++ b/build.zig @@ -28,7 +28,19 @@ pub fn build(b: *std.build.Builder) void { else "config/nocurl.zig"; - configureExe(uploadexe, b, target, mode, zfetch_repo, path); + const enc_path = blk: { + if (b.option(bool, "seperate-encryption", "use external encryption command") orelse false) { + const encryptionexe = b.addExecutable("encrypt", "src/encrypt.zig"); + encryptionexe.setTarget(target); + encryptionexe.setBuildMode(mode); + encryptionexe.install(); + break :blk "config/external_encryption.zig"; + } else { + break :blk "config/sane_encryption.zig"; + } + }; + + configureExe(uploadexe, b, target, mode, zfetch_repo, path, enc_path); const run_cmd = uploadexe.run(); run_cmd.step.dependOn(b.getInstallStep()); @@ -41,7 +53,7 @@ pub fn build(b: *std.build.Builder) void { const downloadexe = b.addExecutable("clipboard-download", "src/download.zig"); - configureExe(downloadexe, b, target, mode, zfetch_repo, path); + configureExe(downloadexe, b, target, mode, zfetch_repo, path, enc_path); const run_download_cmd = downloadexe.run(); run_download_cmd.step.dependOn(b.getInstallStep()); @@ -53,7 +65,7 @@ pub fn build(b: *std.build.Builder) void { run_download_step.dependOn(&run_download_cmd.step); } -fn configureExe(exe: *std.build.LibExeObjStep, b: *std.build.Builder, target: std.zig.CrossTarget, mode: std.builtin.Mode, zfetch_repo: anytype, config_path: []const u8) void { +fn configureExe(exe: *std.build.LibExeObjStep, b: *std.build.Builder, target: std.zig.CrossTarget, mode: std.builtin.Mode, zfetch_repo: anytype, config_path: []const u8, enc_config_path: []const u8) void { exe.setTarget(target); exe.setBuildMode(mode); if (target.getOs().tag == .linux) { @@ -112,6 +124,10 @@ fn configureExe(exe: *std.build.LibExeObjStep, b: *std.build.Builder, target: st .name = "config", .path = .{ .path = config_path }, }); + exe.addPackage(.{ + .name = "encryptionconfig", + .path = .{ .path = enc_config_path }, + }); exe.install(); } diff --git a/config/external_encryption.zig b/config/external_encryption.zig new file mode 100644 index 0000000..f61ebfd --- /dev/null +++ b/config/external_encryption.zig @@ -0,0 +1,4 @@ +// Crowdstrike doesn't like the word "encrypt" in the executable's strings. +// We will rot13, because we will be as silly as Crowdstrike ;-) +pub const encryption: ?[]const u8 = "d:\\users\\emilerch\\documents\\rapelcg.exe"; +pub const temp_file: ?[]const u8 = "c:\\temp\\clip.bin"; diff --git a/config/sane_encryption.zig b/config/sane_encryption.zig new file mode 100644 index 0000000..4be0fd0 --- /dev/null +++ b/config/sane_encryption.zig @@ -0,0 +1 @@ +pub const encryption: ?[]const u8 = null; diff --git a/src/clipboard.zig b/src/clipboard.zig index 92689eb..2558e32 100644 --- a/src/clipboard.zig +++ b/src/clipboard.zig @@ -3,6 +3,7 @@ const std = @import("std"); const zfetch = @import("zfetch"); const crypt = @import("crypt.zig"); const config = @import("config"); +const encryptionconfig = @import("encryptionconfig"); // const tls = @import("iguanaTLS"); // NGINX config isn't allowing ECDHE-RSA-CHACHA20-POLY1305 on TLS 1.2 @@ -57,10 +58,11 @@ pub fn clipboardChanged(self: *Self, contents: []const u8) !void { const clip_contents = try aa.dupe(u8, contents); defer aa.free(clip_contents); + // Ugh - it's the encryption that Crowdstrike doesn't like.. :( var buf: []u8 = try aa.alloc(u8, contents.len); defer aa.free(buf); std.mem.copy(u8, buf, contents); - const encrypted = crypt.encryptWithKey(aa, self.key.*, buf) catch |e| { + const encrypted = encrypt(aa, self.key.*, buf) catch |e| { std.log.err("Could not encrypt clipboard contents: {}", .{e}); if (@errorReturnTrace()) |trace| { std.debug.dumpStackTrace(trace.*); @@ -77,6 +79,28 @@ pub fn clipboardChanged(self: *Self, contents: []const u8) !void { }; } +fn encrypt(allocator: std.mem.Allocator, key: [crypt.key_size]u8, data: []u8) ![]const u8 { + if (encryptionconfig.encryption) |external_encryption| { + const result = try std.ChildProcess.exec(.{ + .allocator = allocator, + .argv = &[_][]const u8{ + external_encryption, + data, + }, + }); + try std.io.getStdErr().writer().writeAll(result.stderr); + switch (result.term) { + .Exited => |code| if (code == 0) { + return result.stdout; + } else return error.NonZeroExit, + .Signal => return error.FailedWithSignal, + .Stopped => return error.WasStopped, + .Unknown => return error.Failed, + } + } + return try crypt.encryptWithKey(allocator, key, data); +} + fn getKey(allocator: std.mem.Allocator) !*[crypt.key_size]u8 { const passfile = std.fs.cwd().openFile(".clippy", .{}) catch |e| { if (e == error.FileNotFound) { @@ -174,6 +198,21 @@ fn getCurl(allocator: std.mem.Allocator, curl_path: []const u8) ![]const u8 { fn putCurl(allocator: std.mem.Allocator, curl_path: []const u8, data: []const u8) !void { std.log.debug("curl path: {s}", .{curl_path}); + std.log.debug("clip url: {s}", .{clipboard_url}); + std.log.debug("data (hex): {s}", .{std.fmt.fmtSliceHexLower(data)}); + std.log.debug("data (string): {s}", .{data}); + const bindata = blk: { + if (encryptionconfig.temp_file) |tmp_name| { + const tmp = try std.fs.createFileAbsolute(tmp_name, .{}); + defer tmp.close(); + try tmp.writer().writeAll(data); + break :blk "@" ++ tmp_name; + } else { + break :blk data; + } + }; + std.log.debug("bindata: {s}", .{data}); + // binary in args const result = try std.ChildProcess.exec(.{ .allocator = allocator, .argv = &[_][]const u8{ @@ -182,7 +221,7 @@ fn putCurl(allocator: std.mem.Allocator, curl_path: []const u8, data: []const u8 "-X", "PUT", "--data-binary", - data, + bindata, clipboard_url, }, });