159 lines
5.1 KiB
Zig
159 lines
5.1 KiB
Zig
|
const std = @import("std");
|
||
|
const builtin = @import("builtin");
|
||
|
const Config = @import("config.zig").Config;
|
||
|
const ansi = @import("anzi").ANSI(.{});
|
||
|
|
||
|
const kex_algorithms = [_][]const u8{
|
||
|
"diffie-hellman-group14-sha1",
|
||
|
"diffie-hellman-group1-sha1",
|
||
|
"diffie-hellman-group-exchange-sha1",
|
||
|
"diffie-hellman-group-exchange-sha256",
|
||
|
"ecdh-sha2-nistp256",
|
||
|
};
|
||
|
|
||
|
const ciphers = [_][]const u8{
|
||
|
"aes256-cbc",
|
||
|
"aes192-cbc",
|
||
|
"3des-cbc",
|
||
|
"aes128-cbc",
|
||
|
"aes256-ctr",
|
||
|
"aes192-ctr",
|
||
|
"aes128-ctr",
|
||
|
};
|
||
|
|
||
|
const macs = [_][]const u8{
|
||
|
"hmac-md5",
|
||
|
"hmac-sha1",
|
||
|
"hmac-sha2-256-etm@openssh.com",
|
||
|
"hmac-sha2-512-etm@openssh.com",
|
||
|
"hmac-sha2-256",
|
||
|
"hmac-sha2-512",
|
||
|
};
|
||
|
|
||
|
const options = [_]struct { key: []const u8, value: []const u8 }{
|
||
|
.{ .key = "ControlMaster", .value = "no" },
|
||
|
.{ .key = "ControlPath", .value = "none" },
|
||
|
.{ .key = "ForwardX11", .value = "no" },
|
||
|
.{ .key = "ForwardX11Trusted", .value = "no" },
|
||
|
.{ .key = "HostKeyAlgorithms", .value = "+ssh-rsa" },
|
||
|
.{ .key = "PubkeyAcceptedKeyTypes", .value = "+ssh-rsa" },
|
||
|
};
|
||
|
|
||
|
pub fn connect(
|
||
|
allocator: std.mem.Allocator,
|
||
|
config_path: []const u8,
|
||
|
identities: ?[][]const u8,
|
||
|
proxy_jump: ?[]const u8,
|
||
|
ssh_path: []const u8,
|
||
|
telnet_path: []const u8,
|
||
|
) !void {
|
||
|
var arena = std.heap.ArenaAllocator.init(allocator);
|
||
|
const alloc = arena.allocator();
|
||
|
defer arena.deinit();
|
||
|
|
||
|
const config = try Config.read(alloc, config_path);
|
||
|
|
||
|
var path: []const u8 = undefined;
|
||
|
var args = std.ArrayList([]const u8).init(alloc);
|
||
|
|
||
|
std.log.info("name: {s}", .{config.name});
|
||
|
std.log.info("class {s}", .{config.class});
|
||
|
std.log.info("type: {}", .{config.type});
|
||
|
std.log.info("comment: {s}", .{config.comment});
|
||
|
std.log.info("address: {s}", .{config.address});
|
||
|
std.log.info("port: {d}", .{config.port});
|
||
|
std.log.info("username: {s}", .{config.username});
|
||
|
std.log.info("manufacturer: {s}", .{config.manufacturer});
|
||
|
std.log.info("model: {s}", .{config.model});
|
||
|
std.log.info("part number: {s}", .{config.part_number});
|
||
|
|
||
|
switch (config.type) {
|
||
|
.ssh => {
|
||
|
path = ssh_path;
|
||
|
try args.append("ssh");
|
||
|
try args.append("-y");
|
||
|
|
||
|
if (identities) |i| {
|
||
|
for (i) |identity| {
|
||
|
try args.append("-i");
|
||
|
try args.append(identity);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (proxy_jump) |p| {
|
||
|
try args.append("-o");
|
||
|
try args.append(try std.fmt.allocPrint(alloc, "ProxyJump={s}", .{p}));
|
||
|
}
|
||
|
|
||
|
for (options) |option| {
|
||
|
try args.append("-o");
|
||
|
try args.append(try std.fmt.allocPrint(alloc, "{s}={s}", .{ option.key, option.value }));
|
||
|
}
|
||
|
|
||
|
try args.append("-o");
|
||
|
try args.append(try std.fmt.allocPrint(alloc, "Ciphers={s}", .{try std.mem.join(alloc, ",", &ciphers)}));
|
||
|
|
||
|
try args.append("-o");
|
||
|
try args.append(try std.fmt.allocPrint(alloc, "KexAlgorithms={s}", .{try std.mem.join(alloc, ",", &kex_algorithms)}));
|
||
|
|
||
|
try args.append("-o");
|
||
|
try args.append(try std.fmt.allocPrint(alloc, "MACs={s}", .{try std.mem.join(alloc, ",", &macs)}));
|
||
|
|
||
|
try args.append("-l");
|
||
|
try args.append(config.username);
|
||
|
|
||
|
if (config.port != 22) {
|
||
|
try args.append("-p");
|
||
|
try args.append(try std.fmt.allocPrint(alloc, "{d}", .{config.port}));
|
||
|
}
|
||
|
|
||
|
try args.append(config.address);
|
||
|
},
|
||
|
|
||
|
.telnet => {
|
||
|
if (proxy_jump) |p| {
|
||
|
path = ssh_path;
|
||
|
try args.append("ssh");
|
||
|
try args.append("-t");
|
||
|
try args.append(try std.fmt.allocPrint(alloc, "ssh://{s}", .{p}));
|
||
|
try args.append("telnet");
|
||
|
} else {
|
||
|
path = telnet_path;
|
||
|
try args.append("telnet");
|
||
|
}
|
||
|
|
||
|
try args.append(config.address);
|
||
|
|
||
|
if (config.port != 23) {
|
||
|
try args.append(try std.fmt.allocPrint(alloc, "{d}", .{config.port}));
|
||
|
}
|
||
|
},
|
||
|
}
|
||
|
|
||
|
const pathZ = try alloc.dupeZ(u8, path);
|
||
|
const argsZ = try alloc.allocSentinel(?[*:0]const u8, args.items.len, null);
|
||
|
for (args.items, 0..) |arg, i| argsZ[i] = (try alloc.dupeZ(u8, arg)).ptr;
|
||
|
|
||
|
for (argsZ, 0..) |arg, i| {
|
||
|
if (arg) |a| std.log.info("{d} {s}", .{ i, a });
|
||
|
}
|
||
|
|
||
|
if (builtin.output_mode == .Exe) {
|
||
|
const stdout_file = std.io.getStdOut().writer();
|
||
|
var bw = std.io.bufferedWriter(stdout_file);
|
||
|
const stdout = bw.writer();
|
||
|
try stdout.print(
|
||
|
"{}",
|
||
|
.{
|
||
|
ansi.IconNameAndWindowTitle{
|
||
|
.icon_name = config.name,
|
||
|
.window_title = try std.fmt.allocPrint(alloc, "{s} \u{2013} {s}", .{ config.name, config.address }),
|
||
|
},
|
||
|
},
|
||
|
);
|
||
|
try bw.flush();
|
||
|
const envp = @as([*:null]const ?[*:0]const u8, @ptrCast(std.os.environ.ptr));
|
||
|
return std.os.execveZ(pathZ, argsZ, envp);
|
||
|
}
|
||
|
}
|