mirror of https://github.com/fairyglade/ly.git
Make code more portable + remove mcookie usage
Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
parent
1314c57796
commit
61f3fadfbf
|
@ -158,9 +158,6 @@ term_reset_cmd = $PREFIX_DIRECTORY/bin/tput reset
|
|||
# Terminal restore cursor command
|
||||
term_restore_cursor_cmd = $PREFIX_DIRECTORY/bin/tput cnorm
|
||||
|
||||
# Cookie generator
|
||||
mcookie_cmd = $PREFIX_DIRECTORY/bin/mcookie
|
||||
|
||||
# Wayland setup command
|
||||
wayland_cmd = $CONFIG_DIRECTORY/ly/wsetup.sh
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ err_dgn_oob = log message
|
|||
err_domain = invalid domain
|
||||
err_envlist = failed to get envlist
|
||||
err_hostname = failed to get hostname
|
||||
err_mcookie = mcookie command failed
|
||||
err_mlock = failed to lock password memory
|
||||
err_null = null pointer
|
||||
err_pam = pam transaction failed
|
||||
|
|
|
@ -11,7 +11,6 @@ err_dgn_oob = message
|
|||
err_domain = domaine invalide
|
||||
err_envlist = échec de lecture de la liste d'environnement
|
||||
err_hostname = échec de lecture du nom d'hôte
|
||||
err_mcookie = échec de la commande mcookie
|
||||
err_mlock = échec du verrouillage mémoire
|
||||
err_null = pointeur null
|
||||
err_pam = échec de la transaction pam
|
||||
|
|
106
src/auth.zig
106
src/auth.zig
|
@ -8,6 +8,7 @@ const Session = @import("tui/components/Session.zig");
|
|||
const Text = @import("tui/components/Text.zig");
|
||||
const Config = @import("config/Config.zig");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Md5 = std.crypto.hash.Md5;
|
||||
const utmp = interop.utmp;
|
||||
const Utmp = utmp.utmpx;
|
||||
const SharedError = @import("SharedError.zig");
|
||||
|
@ -42,7 +43,7 @@ pub fn authenticate(config: Config, current_environment: Session.Environment, lo
|
|||
};
|
||||
var handle: ?*interop.pam.pam_handle = undefined;
|
||||
|
||||
var status = interop.pam.pam_start(config.service_name.ptr, null, &conv, &handle);
|
||||
var status = interop.pam.pam_start(config.service_name, null, &conv, &handle);
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
defer _ = interop.pam.pam_end(handle, status);
|
||||
|
||||
|
@ -65,19 +66,19 @@ pub fn authenticate(config: Config, current_environment: Session.Environment, lo
|
|||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
defer status = interop.pam.pam_close_session(handle, 0);
|
||||
|
||||
var pwd: *std.c.passwd = undefined;
|
||||
var pwd: *interop.pwd.passwd = undefined;
|
||||
{
|
||||
defer interop.endpwent();
|
||||
defer interop.pwd.endpwent();
|
||||
|
||||
// Get password structure from username
|
||||
pwd = std.c.getpwnam(login.ptr) orelse return error.GetPasswordNameFailed;
|
||||
pwd = interop.pwd.getpwnam(login) orelse return error.GetPasswordNameFailed;
|
||||
}
|
||||
|
||||
// Set user shell if it hasn't already been set
|
||||
if (pwd.pw_shell == null) {
|
||||
interop.setusershell();
|
||||
pwd.pw_shell = interop.getusershell();
|
||||
interop.endusershell();
|
||||
interop.unistd.setusershell();
|
||||
pwd.pw_shell = interop.unistd.getusershell();
|
||||
interop.unistd.endusershell();
|
||||
}
|
||||
|
||||
var shared_err = try SharedError.init();
|
||||
|
@ -123,18 +124,22 @@ pub fn authenticate(config: Config, current_environment: Session.Environment, lo
|
|||
|
||||
fn startSession(
|
||||
config: Config,
|
||||
pwd: *std.c.passwd,
|
||||
pwd: *interop.pwd.passwd,
|
||||
handle: ?*interop.pam.pam_handle,
|
||||
current_environment: Session.Environment,
|
||||
) !void {
|
||||
const status = interop.initgroups(pwd.pw_name.?, pwd.pw_gid);
|
||||
if (builtin.os.tag == .freebsd) {
|
||||
// FreeBSD has initgroups() in unistd
|
||||
const status = interop.unistd.initgroups(pwd.pw_name, pwd.pw_gid);
|
||||
if (status != 0) return error.GroupInitializationFailed;
|
||||
|
||||
if (builtin.os.tag == .freebsd) {
|
||||
// FreeBSD sets the GID and UID with setusercontext()
|
||||
const result = std.c.setusercontext(null, pwd, pwd.pw_uid, interop.logincap.LOGIN_SETALL);
|
||||
if (result != 0) return error.SetUserUidFailed;
|
||||
} else {
|
||||
const status = interop.grp.initgroups(pwd.pw_name, pwd.pw_gid);
|
||||
if (status != 0) return error.GroupInitializationFailed;
|
||||
|
||||
std.posix.setgid(pwd.pw_gid) catch return error.SetUserGidFailed;
|
||||
std.posix.setuid(pwd.pw_uid) catch return error.SetUserUidFailed;
|
||||
}
|
||||
|
@ -147,7 +152,7 @@ fn startSession(
|
|||
if (pam_env_vars == null) return error.GetEnvListFailed;
|
||||
|
||||
const env_list = std.mem.span(pam_env_vars.?);
|
||||
for (env_list) |env_var| _ = interop.putenv(env_var.?);
|
||||
for (env_list) |env_var| _ = interop.stdlib.putenv(env_var);
|
||||
|
||||
// Execute what the user requested
|
||||
std.posix.chdirZ(pwd.pw_dir.?) catch return error.ChangeDirectoryFailed;
|
||||
|
@ -165,21 +170,21 @@ fn startSession(
|
|||
}
|
||||
}
|
||||
|
||||
fn initEnv(pwd: *std.c.passwd, path_env: ?[:0]const u8) !void {
|
||||
_ = interop.setenv("HOME", pwd.pw_dir, 1);
|
||||
_ = interop.setenv("PWD", pwd.pw_dir, 1);
|
||||
_ = interop.setenv("SHELL", pwd.pw_shell, 1);
|
||||
_ = interop.setenv("USER", pwd.pw_name, 1);
|
||||
_ = interop.setenv("LOGNAME", pwd.pw_name, 1);
|
||||
fn initEnv(pwd: *interop.pwd.passwd, path_env: ?[:0]const u8) !void {
|
||||
_ = interop.stdlib.setenv("HOME", pwd.pw_dir, 1);
|
||||
_ = interop.stdlib.setenv("PWD", pwd.pw_dir, 1);
|
||||
_ = interop.stdlib.setenv("SHELL", pwd.pw_shell, 1);
|
||||
_ = interop.stdlib.setenv("USER", pwd.pw_name, 1);
|
||||
_ = interop.stdlib.setenv("LOGNAME", pwd.pw_name, 1);
|
||||
|
||||
if (path_env) |path| {
|
||||
const status = interop.setenv("PATH", path, 1);
|
||||
const status = interop.stdlib.setenv("PATH", path, 1);
|
||||
if (status != 0) return error.SetPathFailed;
|
||||
}
|
||||
}
|
||||
|
||||
fn setXdgSessionEnv(display_server: enums.DisplayServer) void {
|
||||
_ = interop.setenv("XDG_SESSION_TYPE", switch (display_server) {
|
||||
_ = interop.stdlib.setenv("XDG_SESSION_TYPE", switch (display_server) {
|
||||
.wayland => "wayland",
|
||||
.shell => "tty",
|
||||
.xinitrc, .x11 => "x11",
|
||||
|
@ -192,19 +197,19 @@ fn setXdgEnv(tty_str: [:0]u8, desktop_name: [:0]const u8, xdg_desktop_names: [:0
|
|||
// XDG_RUNTIME_DIR to fall back to directories inside user's home
|
||||
// directory.
|
||||
if (builtin.os.tag != .freebsd) {
|
||||
const uid = interop.getuid();
|
||||
const uid = interop.unistd.getuid();
|
||||
var uid_buffer: [10 + @sizeOf(u32) + 1]u8 = undefined;
|
||||
const uid_str = try std.fmt.bufPrintZ(&uid_buffer, "/run/user/{d}", .{uid});
|
||||
|
||||
_ = interop.setenv("XDG_RUNTIME_DIR", uid_str.ptr, 0);
|
||||
_ = interop.stdlib.setenv("XDG_RUNTIME_DIR", uid_str, 0);
|
||||
}
|
||||
|
||||
_ = interop.setenv("XDG_CURRENT_DESKTOP", xdg_desktop_names.ptr, 0);
|
||||
_ = interop.setenv("XDG_SESSION_CLASS", "user", 0);
|
||||
_ = interop.setenv("XDG_SESSION_ID", "1", 0);
|
||||
_ = interop.setenv("XDG_SESSION_DESKTOP", desktop_name.ptr, 0);
|
||||
_ = interop.setenv("XDG_SEAT", "seat0", 0);
|
||||
_ = interop.setenv("XDG_VTNR", tty_str.ptr, 0);
|
||||
_ = interop.stdlib.setenv("XDG_CURRENT_DESKTOP", xdg_desktop_names, 0);
|
||||
_ = interop.stdlib.setenv("XDG_SESSION_CLASS", "user", 0);
|
||||
_ = interop.stdlib.setenv("XDG_SESSION_ID", "1", 0);
|
||||
_ = interop.stdlib.setenv("XDG_SESSION_DESKTOP", desktop_name, 0);
|
||||
_ = interop.stdlib.setenv("XDG_SEAT", "seat0", 0);
|
||||
_ = interop.stdlib.setenv("XDG_VTNR", tty_str, 0);
|
||||
}
|
||||
|
||||
fn loginConv(
|
||||
|
@ -235,7 +240,7 @@ fn loginConv(
|
|||
status = interop.pam.PAM_BUF_ERR;
|
||||
break :set_credentials;
|
||||
};
|
||||
response[i].resp = username.?.ptr;
|
||||
response[i].resp = username.?;
|
||||
},
|
||||
interop.pam.PAM_PROMPT_ECHO_OFF => {
|
||||
const data: [*][*:0]u8 = @ptrCast(@alignCast(appdata_ptr));
|
||||
|
@ -243,7 +248,7 @@ fn loginConv(
|
|||
status = interop.pam.PAM_BUF_ERR;
|
||||
break :set_credentials;
|
||||
};
|
||||
response[i].resp = password.?.ptr;
|
||||
response[i].resp = password.?;
|
||||
},
|
||||
interop.pam.PAM_ERROR_MSG => {
|
||||
status = interop.pam.PAM_CONV_ERR;
|
||||
|
@ -349,49 +354,30 @@ fn createXauthFile(pwd: [:0]const u8) ![:0]const u8 {
|
|||
return xauthority;
|
||||
}
|
||||
|
||||
pub fn mcookie(cmd: [:0]const u8) ![32]u8 {
|
||||
const pipe = try std.posix.pipe();
|
||||
defer std.posix.close(pipe[1]);
|
||||
fn mcookie() [Md5.digest_length * 2]u8 {
|
||||
var buf: [4096]u8 = undefined;
|
||||
std.crypto.random.bytes(&buf);
|
||||
|
||||
const output = std.fs.File{ .handle = pipe[0] };
|
||||
defer output.close();
|
||||
var out: [Md5.digest_length]u8 = undefined;
|
||||
Md5.hash(&buf, &out, .{});
|
||||
|
||||
const pid = try std.posix.fork();
|
||||
if (pid == 0) {
|
||||
std.posix.close(pipe[0]);
|
||||
|
||||
std.posix.dup2(pipe[1], std.posix.STDOUT_FILENO) catch std.process.exit(1);
|
||||
std.posix.close(pipe[1]);
|
||||
|
||||
const args = [_:null]?[*:0]u8{};
|
||||
std.posix.execveZ(cmd.ptr, &args, std.c.environ) catch {};
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
const result = std.posix.waitpid(pid, 0);
|
||||
|
||||
if (result.status != 0) return error.McookieFailed;
|
||||
|
||||
var buf: [32]u8 = undefined;
|
||||
const len = try output.read(&buf);
|
||||
if (len != 32) return error.McookieFailed;
|
||||
return buf;
|
||||
return std.fmt.bytesToHex(&out, .lower);
|
||||
}
|
||||
|
||||
fn xauth(display_name: [:0]u8, shell: [*:0]const u8, pw_dir: [*:0]const u8, xauth_cmd: []const u8, mcookie_cmd: [:0]const u8) !void {
|
||||
fn xauth(display_name: [:0]u8, shell: [*:0]const u8, pw_dir: [*:0]const u8, xauth_cmd: []const u8) !void {
|
||||
var pwd_buf: [100]u8 = undefined;
|
||||
const pwd = try std.fmt.bufPrintZ(&pwd_buf, "{s}", .{pw_dir});
|
||||
|
||||
const xauthority = try createXauthFile(pwd);
|
||||
_ = interop.setenv("XAUTHORITY", xauthority, 1);
|
||||
_ = interop.setenv("DISPLAY", display_name, 1);
|
||||
_ = interop.stdlib.setenv("XAUTHORITY", xauthority, 1);
|
||||
_ = interop.stdlib.setenv("DISPLAY", display_name, 1);
|
||||
|
||||
const mcookie_output = try mcookie(mcookie_cmd);
|
||||
const magic_cookie = mcookie();
|
||||
|
||||
const pid = try std.posix.fork();
|
||||
if (pid == 0) {
|
||||
var cmd_buffer: [1024]u8 = undefined;
|
||||
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} add {s} . {s}", .{ xauth_cmd, display_name, mcookie_output }) catch std.process.exit(1);
|
||||
const cmd_str = std.fmt.bufPrintZ(&cmd_buffer, "{s} add {s} . {s}", .{ xauth_cmd, display_name, magic_cookie }) catch std.process.exit(1);
|
||||
const args = [_:null]?[*:0]const u8{ shell, "-c", cmd_str };
|
||||
std.posix.execveZ(shell, &args, std.c.environ) catch {};
|
||||
std.process.exit(1);
|
||||
|
@ -417,7 +403,7 @@ fn executeX11Cmd(shell: [*:0]const u8, pw_dir: [*:0]const u8, config: Config, de
|
|||
const display_num = try getFreeDisplay();
|
||||
var buf: [5]u8 = undefined;
|
||||
const display_name = try std.fmt.bufPrintZ(&buf, ":{d}", .{display_num});
|
||||
try xauth(display_name, shell, pw_dir, config.xauth_cmd, config.mcookie_cmd);
|
||||
try xauth(display_name, shell, pw_dir, config.xauth_cmd);
|
||||
|
||||
const pid = try std.posix.fork();
|
||||
if (pid == 0) {
|
||||
|
|
|
@ -28,7 +28,6 @@ lang: []const u8 = "en",
|
|||
load: bool = true,
|
||||
margin_box_h: u8 = 2,
|
||||
margin_box_v: u8 = 1,
|
||||
mcookie_cmd: [:0]const u8 = build_options.prefix_directory ++ "/bin/mcookie",
|
||||
min_refresh_delta: u16 = 5,
|
||||
numlock: bool = false,
|
||||
path: ?[:0]const u8 = "/sbin:/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin",
|
||||
|
|
|
@ -12,7 +12,6 @@ err_dgn_oob: []const u8 = "log message",
|
|||
err_domain: []const u8 = "invalid domain",
|
||||
err_envlist: []const u8 = "failed to get envlist",
|
||||
err_hostname: []const u8 = "failed to get hostname",
|
||||
err_mcookie: []const u8 = "mcookie command failed",
|
||||
err_mlock: []const u8 = "failed to lock password memory",
|
||||
err_null: []const u8 = "null pointer",
|
||||
err_pam: []const u8 = "pam transaction failed",
|
||||
|
|
|
@ -62,7 +62,8 @@ pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniFie
|
|||
if (std.mem.eql(u8, field.key, "wayland_specifier") or
|
||||
std.mem.eql(u8, field.key, "max_desktop_len") or
|
||||
std.mem.eql(u8, field.key, "max_login_len") or
|
||||
std.mem.eql(u8, field.key, "max_password_len"))
|
||||
std.mem.eql(u8, field.key, "max_password_len") or
|
||||
std.mem.eql(u8, field.key, "mcookie_cmd"))
|
||||
{
|
||||
// The options don't exist anymore
|
||||
mapped_config_fields = true;
|
||||
|
|
|
@ -21,6 +21,22 @@ pub const unistd = @cImport({
|
|||
@cInclude("unistd.h");
|
||||
});
|
||||
|
||||
pub const time = @cImport({
|
||||
@cInclude("time.h");
|
||||
});
|
||||
|
||||
pub const stdlib = @cImport({
|
||||
@cInclude("stdlib.h");
|
||||
});
|
||||
|
||||
pub const pwd = @cImport({
|
||||
@cInclude("pwd.h");
|
||||
});
|
||||
|
||||
pub const grp = @cImport({
|
||||
@cInclude("grp.h");
|
||||
});
|
||||
|
||||
// FreeBSD-specific headers
|
||||
pub const logincap = @cImport({
|
||||
@cInclude("login_cap.h");
|
||||
|
@ -40,38 +56,18 @@ pub const vt = @cImport({
|
|||
@cInclude("sys/vt.h");
|
||||
});
|
||||
|
||||
pub const c_size = usize;
|
||||
pub const c_uid = u32;
|
||||
pub const c_gid = u32;
|
||||
pub const c_time = c_longlong;
|
||||
pub const tm = extern struct {
|
||||
tm_sec: c_int,
|
||||
tm_min: c_int,
|
||||
tm_hour: c_int,
|
||||
tm_mday: c_int,
|
||||
tm_mon: c_int,
|
||||
tm_year: c_int,
|
||||
tm_wday: c_int,
|
||||
tm_yday: c_int,
|
||||
tm_isdst: c_int,
|
||||
};
|
||||
|
||||
pub extern "c" fn localtime(timer: *const c_time) *tm;
|
||||
pub extern "c" fn strftime(str: [*:0]u8, maxsize: c_size, format: [*:0]const u8, timeptr: *const tm) c_size;
|
||||
pub extern "c" fn setenv(name: [*:0]const u8, value: ?[*:0]const u8, overwrite: c_int) c_int;
|
||||
pub extern "c" fn putenv(name: [*:0]u8) c_int;
|
||||
pub extern "c" fn getuid() c_uid;
|
||||
pub extern "c" fn endpwent() void;
|
||||
pub extern "c" fn setusershell() void;
|
||||
pub extern "c" fn getusershell() [*:0]u8;
|
||||
pub extern "c" fn endusershell() void;
|
||||
pub extern "c" fn initgroups(user: [*:0]const u8, group: c_gid) c_int;
|
||||
// Used for getting & setting the lock state
|
||||
const LedState = if (builtin.os.tag.isBSD()) c_int else c_char;
|
||||
const get_led_state = if (builtin.os.tag.isBSD()) kbio.KDGETLED else kd.KDGKBLED;
|
||||
const set_led_state = if (builtin.os.tag.isBSD()) kbio.KDSETLED else kd.KDSKBLED;
|
||||
const numlock_led = if (builtin.os.tag.isBSD()) kbio.LED_NUM else kd.K_NUMLOCK;
|
||||
const capslock_led = if (builtin.os.tag.isBSD()) kbio.LED_CAP else kd.K_CAPSLOCK;
|
||||
|
||||
pub fn timeAsString(buf: [:0]u8, format: [:0]const u8) ![]u8 {
|
||||
const timer = std.time.timestamp();
|
||||
const tm_info = localtime(&timer);
|
||||
const tm_info = time.localtime(&timer);
|
||||
|
||||
const len = strftime(buf, buf.len, format, tm_info);
|
||||
const len = time.strftime(buf, buf.len, format, tm_info);
|
||||
if (len < 0) return error.CannotGetFormattedTime;
|
||||
|
||||
return buf[0..len];
|
||||
|
@ -92,47 +88,22 @@ pub fn getLockState(console_dev: []const u8) !struct {
|
|||
const fd = try std.posix.open(console_dev, .{ .ACCMODE = .RDONLY }, 0);
|
||||
defer std.posix.close(fd);
|
||||
|
||||
var numlock = false;
|
||||
var capslock = false;
|
||||
|
||||
if (builtin.os.tag.isBSD()) {
|
||||
var led: c_int = undefined;
|
||||
_ = std.c.ioctl(fd, kbio.KDGETLED, &led);
|
||||
numlock = (led & kbio.LED_NUM) != 0;
|
||||
capslock = (led & kbio.LED_CAP) != 0;
|
||||
} else {
|
||||
var led: c_char = undefined;
|
||||
_ = std.c.ioctl(fd, kd.KDGKBLED, &led);
|
||||
numlock = (led & kd.K_NUMLOCK) != 0;
|
||||
capslock = (led & kd.K_CAPSLOCK) != 0;
|
||||
}
|
||||
var led: LedState = undefined;
|
||||
_ = std.c.ioctl(fd, get_led_state, &led);
|
||||
|
||||
return .{
|
||||
.numlock = numlock,
|
||||
.capslock = capslock,
|
||||
.numlock = (led & numlock_led) != 0,
|
||||
.capslock = (led & capslock_led) != 0,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn setNumlock(val: bool) !void {
|
||||
if (builtin.os.tag.isBSD()) {
|
||||
var led: c_int = undefined;
|
||||
_ = std.c.ioctl(0, kbio.KDGETLED, &led);
|
||||
var led: LedState = undefined;
|
||||
_ = std.c.ioctl(0, get_led_state, &led);
|
||||
|
||||
const numlock = (led & kbio.LED_NUM) != 0;
|
||||
const numlock = (led & numlock_led) != 0;
|
||||
if (numlock != val) {
|
||||
const status = std.c.ioctl(std.posix.STDIN_FILENO, kbio.KDSETLED, led ^ kbio.LED_NUM);
|
||||
if (status != 0) return error.FailedToSetNumlock;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var led: c_char = undefined;
|
||||
_ = std.c.ioctl(0, kd.KDGKBLED, &led);
|
||||
|
||||
const numlock = (led & kd.K_NUMLOCK) != 0;
|
||||
if (numlock != val) {
|
||||
const status = std.c.ioctl(std.posix.STDIN_FILENO, kd.KDSKBLED, led ^ kd.K_NUMLOCK);
|
||||
const status = std.c.ioctl(std.posix.STDIN_FILENO, set_led_state, led ^ numlock_led);
|
||||
if (status != 0) return error.FailedToSetNumlock;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ pub fn main() !void {
|
|||
const labels_max_length = @max(lang.login.len, lang.password.len);
|
||||
|
||||
var seed: u64 = undefined;
|
||||
try std.posix.getrandom(std.mem.asBytes(&seed)); // Get a random seed for the PRNG (used by animations)
|
||||
std.crypto.random.bytes(std.mem.asBytes(&seed)); // Get a random seed for the PRNG (used by animations)
|
||||
|
||||
var prng = std.Random.DefaultPrng.init(seed);
|
||||
const random = prng.random();
|
||||
|
@ -770,7 +770,6 @@ fn getAuthErrorMsg(err: anyerror, lang: Lang) []const u8 {
|
|||
error.GetPasswordNameFailed => lang.err_pwnam,
|
||||
error.GetEnvListFailed => lang.err_envlist,
|
||||
error.XauthFailed => lang.err_xauth,
|
||||
error.McookieFailed => lang.err_mcookie,
|
||||
error.XcbConnectionFailed => lang.err_xcb_conn,
|
||||
error.GroupInitializationFailed => lang.err_user_init,
|
||||
error.SetUserGidFailed => lang.err_user_gid,
|
||||
|
|
Loading…
Reference in New Issue