ztacacs/src/packet.zig
2023-09-21 10:54:27 -05:00

190 lines
5 KiB
Zig

const std = @import("std");
const serde = @import("serde.zig");
pub const MajorVersion = enum(u4) {
Default = 0xc,
_,
};
pub const MinorVersion = enum(u4) {
Default = 0x0,
One = 0x1,
_,
};
pub const PacketType = enum(u8) {
Authentication = 1,
Authorization = 2,
Accounting = 3,
_,
};
pub const HeaderFlags = packed struct(u8) {
Unencrypted: bool = false,
_p1: u1 = 0,
SingleConnect: bool = false,
_p2: u5 = 0,
pub fn format(value: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) std.os.WriteError!void {
try writer.print("{s}{{ .Unencrypted = {}, .SingleConnect = {} }}", .{
@typeName(@This()),
value.Unencrypted,
value.SingleConnect,
});
}
};
pub const Header = struct {
major: MajorVersion,
minor: MinorVersion,
type: PacketType,
seq_no: u8,
flags: HeaderFlags,
session_id: u32,
length: u32,
};
test "header 1" {
const packet = [_]u8{ 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
var reader = serde.Reader.init(&packet);
const header = try reader.read(Header);
std.debug.print("{}\n", .{header});
try std.testing.expect(header.major == .Default);
try std.testing.expect(header.minor == .Default);
try std.testing.expect(header.type == .Authentication);
try std.testing.expect(header.seq_no == 0);
try std.testing.expect(!header.flags.Unencrypted);
try std.testing.expect(!header.flags.SingleConnect);
try std.testing.expect(header.session_id == 0);
try std.testing.expect(header.length == 0);
}
test "header 2" {
const packet = [_]u8{ 0xc0, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
var reader = serde.Reader.init(&packet);
const header = try reader.read(Header);
std.debug.print("{}\n", .{header});
try std.testing.expect(header.major == .Default);
try std.testing.expect(header.minor == .Default);
try std.testing.expect(header.type == .Authorization);
try std.testing.expect(header.seq_no == 2);
try std.testing.expect(header.flags.Unencrypted);
try std.testing.expect(!header.flags.SingleConnect);
try std.testing.expect(header.session_id == 0);
try std.testing.expect(header.length == 0);
}
test "header 3" {
const packet = [_]u8{ 0xc0, 0x03, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
var reader = serde.Reader.init(&packet);
const header = try reader.read(Header);
std.debug.print("{}\n", .{header});
try std.testing.expect(header.major == .Default);
try std.testing.expect(header.minor == .Default);
try std.testing.expect(header.type == .Accounting);
try std.testing.expect(header.seq_no == 255);
try std.testing.expect(!header.flags.Unencrypted);
try std.testing.expect(header.flags.SingleConnect);
try std.testing.expect(header.session_id == 0);
try std.testing.expect(header.length == 0);
}
pub const AuthenticationAction = enum(u8) {
Login = 0x01,
ChangePassword = 0x02,
SendAuth = 0x03,
_,
};
pub const AuthenticationType = enum(u8) {
ASCII = 0x01,
PAP = 0x02,
CHAP = 0x03,
MSCHAP = 0x05,
MSCHAPV2 = 0x06,
_,
};
pub const AuthenticationService = enum(u8) {
NONE = 0x00,
LOGIN = 0x01,
ENABLE = 0x02,
PPP = 0x03,
PT = 0x05,
RCMD = 0x06,
X25 = 0x07,
NASI = 0x08,
FWPROXY = 0x09,
_,
};
pub const AuthenticationStartHeader = struct {
action: AuthenticationAction,
priv_lvl: u8,
authen_type: AuthenticationType,
authen_service: AuthenticationService,
user_len: u8,
port_len: u8,
rem_addr_len: u8,
data_len: u8,
};
pub const AuthenticationStatus = enum(u8) {
PASS = 0x01,
FAIL = 0x02,
GETDATA = 0x03,
GETUSER = 0x04,
GETPASS = 0x05,
RESTART = 0x06,
ERROR = 0x07,
FOLLOW = 0x21,
};
pub const AuthenticationReplyFlags = packed struct(u8) {
NoEcho: bool,
_p1: u7 = 0,
pub fn format(value: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) std.os.WriteError!void {
try writer.print("{s}{{ .NoEcho = {}, }}", .{
@typeName(@This()),
value.NoEcho,
});
}
};
pub const AuthenticationReplyHeader = struct {
status: AuthenticationStatus,
flags: AuthenticationReplyFlags,
server_msg_len: u16,
data_len: u16,
};
pub const AuthenticationContinueFlags = packed struct(u8) {
Abort: bool,
_p1: u7 = 0,
pub fn format(value: @This(), comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) std.os.WriteError!void {
try writer.print("{s}{{ .Abort = {}, }}", .{
@typeName(@This()),
value.Abort,
});
}
};
pub const AuthenticationContinueHeader = struct {
user_msg: u16,
data_len: u16,
flags: AuthenticationContinueFlags,
};
pub const AuthorizationRequestHeader = struct {
authen_method: u8,
priv_lvl: u8,
authen_type: u8,
authen_service: u8,
user_len: u8,
port_len: u8,
rem_addr_len: u8,
arg_cnt: u8,
};