Merge branch 'master' of codeberg.org:fairyglade/ly into zig-0.17

Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
AnErrupTion
2026-08-25 23:13:21 +02:00
25 changed files with 1248 additions and 616 deletions

View File

@@ -26,6 +26,14 @@ pub const AuthOptions = struct {
use_kmscon_vt: bool,
};
const PamAppdata = struct {
username: []const u8,
password: []const u8,
authreq_requested: bool,
authreq_responded: bool,
new_password: []const u8,
};
var xorg_pid: std.posix.pid_t = 0;
pub fn xorgSignalHandler(sig: std.posix.SIG) callconv(.c) void {
if (xorg_pid > 0) _ = std.c.kill(xorg_pid, sig);
@@ -36,7 +44,15 @@ pub fn sessionSignalHandler(sig: std.posix.SIG) callconv(.c) void {
if (child_pid > 0) _ = std.c.kill(child_pid, sig);
}
pub fn authenticate(allocator: std.mem.Allocator, io: std.Io, log_file: *LogFile, options: AuthOptions, current_environment: Environment, login: []const u8, password: []const u8) !void {
pub fn authenticate(
allocator: std.mem.Allocator,
io: std.Io,
log_file: *LogFile,
options: AuthOptions,
current_environment: Environment,
login: []const u8,
password: []const u8,
) !void {
var tty_buffer: [3]u8 = undefined;
const tty_str = try std.fmt.bufPrint(&tty_buffer, "{d}", .{options.tty});
@@ -49,13 +65,14 @@ pub fn authenticate(allocator: std.mem.Allocator, io: std.Io, log_file: *LogFile
// Open the PAM session
try log_file.info(io, "auth/pam", "encoding credentials", .{});
const login_z = try allocator.dupeSentinel(u8, login, 0);
defer allocator.free(login_z);
const password_z = try allocator.dupeSentinel(u8, password, 0);
defer allocator.free(password_z);
var credentials = [_:null]?[*:0]const u8{ login_z, password_z };
var credentials: PamAppdata = .{
.username = login,
.password = password,
.authreq_requested = false,
.authreq_responded = false,
.new_password = "",
};
const conv = interop.pam.pam_conv{
.conv = loginConv,
@@ -80,6 +97,11 @@ pub fn authenticate(allocator: std.mem.Allocator, io: std.Io, log_file: *LogFile
try log_file.info(io, "auth/pam", "validating account", .{});
status = interop.pam.pam_acct_mgmt(handle, 0);
if (status == interop.pam.PAM_NEW_AUTHTOK_REQD) {
// credentials.authreq_requested = true;
// credentials.new_password = "";
// status = interop.pam.pam_chauthtok(handle, interop.pam.PAM_CHANGE_EXPIRED_AUTHTOK);
}
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
try log_file.info(io, "auth/pam", "setting credentials", .{});
@@ -98,7 +120,7 @@ pub fn authenticate(allocator: std.mem.Allocator, io: std.Io, log_file: *LogFile
defer interop.closePasswordDatabase();
// Get password structure from username
user_entry = interop.getUsernameEntry(login_z) orelse return error.GetPasswordNameFailed;
user_entry = interop.getUsernameEntry(allocator, login) orelse return error.GetPasswordNameFailed;
}
// Set user shell if it hasn't already been set
@@ -276,6 +298,7 @@ fn loginConv(
resp: ?*?[*]interop.pam.pam_response,
appdata_ptr: ?*anyopaque,
) callconv(.c) c_int {
const data: *PamAppdata = @ptrCast(@alignCast(appdata_ptr));
const message_count: u32 = @intCast(num_msg);
const messages = msg.?;
@@ -289,20 +312,36 @@ fn loginConv(
var username: ?[:0]u8 = null;
var password: ?[:0]u8 = null;
var status: c_int = interop.pam.PAM_SUCCESS;
defer {
if (status != interop.pam.PAM_SUCCESS) {
// Memory is freed by pam otherwise
allocator.free(response);
if (username) |str| allocator.free(str);
if (password) |str| allocator.free(str);
} else {
resp.?.* = response.ptr;
}
}
for (0..message_count) |i| set_credentials: {
switch (messages[i].?.msg_style) {
interop.pam.PAM_PROMPT_ECHO_ON => {
const data: [*][*:0]u8 = @ptrCast(@alignCast(appdata_ptr));
username = allocator.dupeSentinel(u8, std.mem.span(data[0]), 0) catch {
username = allocator.dupeZ(u8, data.username) catch {
status = interop.pam.PAM_BUF_ERR;
break :set_credentials;
};
response[i].resp = username.?;
},
interop.pam.PAM_PROMPT_ECHO_OFF => {
const data: [*][*:0]u8 = @ptrCast(@alignCast(appdata_ptr));
password = allocator.dupeSentinel(u8, std.mem.span(data[1]), 0) catch {
var pass = data.password;
if (data.authreq_requested) {
if (data.authreq_responded) {
pass = data.new_password;
}
data.authreq_responded = true;
}
password = allocator.dupeZ(u8, pass) catch {
status = interop.pam.PAM_BUF_ERR;
break :set_credentials;
};
@@ -316,15 +355,6 @@ fn loginConv(
}
}
if (status != interop.pam.PAM_SUCCESS) {
// Memory is freed by pam otherwise
allocator.free(response);
if (username) |str| allocator.free(str);
if (password) |str| allocator.free(str);
} else {
resp.?.* = response.ptr;
}
return status;
}
@@ -574,7 +604,15 @@ fn executeCmd(global_log_file: *LogFile, allocator: std.mem.Allocator, io: std.I
fn redirectStandardStreams(global_log_file: *LogFile, io: std.Io, session_log: []const u8, create: bool) !std.Io.File {
create_session_log_dir: {
const session_log_dir = std.Io.Dir.path.dirname(session_log) orelse break :create_session_log_dir;
std.Io.Dir.cwd().createDirPath(io, session_log_dir) catch |err| {
var buffer = std.mem.zeroes([std.Io.Dir.max_path_bytes]u8);
const len = std.Io.Dir.cwd().realPathFile(io, session_log_dir, &buffer) catch |err| {
try global_log_file.err(io, "auth/sys", "failed to resolve path for session log file directory: {s}", .{@errorName(err)});
return err;
};
const resolved_path = buffer[0..len];
std.Io.Dir.cwd().createDirPath(io, resolved_path) catch |err| {
try global_log_file.err(io, "auth/sys", "failed to create session log file directory: {s}", .{@errorName(err)});
return err;
};