mirror of
https://codeberg.org/fairyglade/ly.git
synced 2026-08-27 07:50:45 +02:00
auth: Check faillock for locked account (closes #898)
Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
parent
c90aec373e
commit
a6e5f87e24
30 changed files with 101 additions and 0 deletions
65
src/auth.zig
65
src/auth.zig
|
|
@ -20,6 +20,7 @@ pub const AuthOptions = struct {
|
|||
xauth_cmd: []const u8,
|
||||
setup_cmd: []const u8,
|
||||
login_cmd: ?[]const u8,
|
||||
faillock_tally_dir: []const u8,
|
||||
x_cmd: []const u8,
|
||||
x_vt: ?u8,
|
||||
session_pid: std.posix.pid_t,
|
||||
|
|
@ -34,6 +35,18 @@ const PamAppdata = struct {
|
|||
new_password: []const u8,
|
||||
};
|
||||
|
||||
//https://github.com/linux-pam/linux-pam/blob/master/modules/pam_faillock/faillock.h#L55
|
||||
const PamFaillockEntry = extern struct {
|
||||
pub const STATUS_VALID: usize = 0x1;
|
||||
pub const STATUS_RHOST: usize = 0x2;
|
||||
pub const STATUS_TTY: usize = 0x4;
|
||||
|
||||
source: [52]u8,
|
||||
reserved: u16,
|
||||
status: u16,
|
||||
time: u64,
|
||||
};
|
||||
|
||||
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);
|
||||
|
|
@ -54,6 +67,11 @@ pub fn authenticate(
|
|||
password: []const u8,
|
||||
maybe_new_password: ?[]const u8,
|
||||
) !void {
|
||||
var faillock_entries: usize = 0;
|
||||
if (try dirExists(io, options.faillock_tally_dir)) {
|
||||
faillock_entries = try getFaillockEntries(allocator, io, login, options.faillock_tally_dir);
|
||||
}
|
||||
|
||||
var tty_buffer: [3]u8 = undefined;
|
||||
const tty_str = try std.fmt.bufPrint(&tty_buffer, "{d}", .{options.tty});
|
||||
|
||||
|
|
@ -94,6 +112,13 @@ pub fn authenticate(
|
|||
// Do the PAM routine
|
||||
try log_file.info(io, "auth/pam", "authenticating", .{});
|
||||
status = interop.pam.pam_authenticate(handle, 0);
|
||||
if (status == interop.pam.PAM_AUTH_ERR and try dirExists(io, options.faillock_tally_dir)) {
|
||||
const new_faillock_entries = try getFaillockEntries(allocator, io, login, options.faillock_tally_dir);
|
||||
|
||||
if (faillock_entries == new_faillock_entries) {
|
||||
return error.AccountLocked;
|
||||
}
|
||||
}
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
|
||||
try log_file.info(io, "auth/pam", "validating account", .{});
|
||||
|
|
@ -188,6 +213,46 @@ pub fn authenticate(
|
|||
if (shared_err.readError()) |err| return err;
|
||||
}
|
||||
|
||||
fn dirExists(io: std.Io, path: []const u8) !bool {
|
||||
var dir = std.Io.Dir.openDirAbsolute(io, path, .{}) catch |err| {
|
||||
if (err == error.FileNotFound) return false;
|
||||
return err;
|
||||
};
|
||||
defer dir.close(io);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fn getFaillockEntries(
|
||||
allocator: std.mem.Allocator,
|
||||
io: std.Io,
|
||||
username: []const u8,
|
||||
tally_dir: []const u8,
|
||||
) !usize {
|
||||
const path = try std.fs.path.join(allocator, &.{ tally_dir, username });
|
||||
defer allocator.free(path);
|
||||
|
||||
var file = try std.Io.Dir.openFileAbsolute(io, path, .{});
|
||||
defer file.close(io);
|
||||
|
||||
var buffer: [1024]u8 = undefined;
|
||||
var reader = file.reader(io, &buffer);
|
||||
var count: usize = 0;
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
const entry = reader.interface.takeStruct(PamFaillockEntry, .little) catch |err| {
|
||||
if (err == error.EndOfStream) break;
|
||||
return err;
|
||||
};
|
||||
|
||||
if (entry.status & PamFaillockEntry.STATUS_VALID != 0) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
fn startSession(
|
||||
log_file: *LogFile,
|
||||
allocator: std.mem.Allocator,
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ dur_y_offset: i32 = 0,
|
|||
edge_margin: u8 = 0,
|
||||
error_bg: u32 = 0x00000000,
|
||||
error_fg: u32 = 0x01FF0000,
|
||||
faillock_tally_dir: []const u8 = "/var/run/faillock",
|
||||
fg: u32 = 0x00FFFFFF,
|
||||
full_color: bool = true,
|
||||
gameoflife_fg: u32 = 0x0000FF00,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ custom: []const u8 = "custom",
|
|||
custom_info_err_output_long: []const u8 = "output too long",
|
||||
custom_info_err_no_output: []const u8 = "no output",
|
||||
custom_info_err_no_output_error: []const u8 = ", possible error",
|
||||
err_acc_locked: []const u8 = "account locked, too many attempts",
|
||||
err_alloc: []const u8 = "failed memory allocation",
|
||||
err_args: []const u8 = "unable to parse command line arguments",
|
||||
err_autologin_session: []const u8 = "autologin session not found",
|
||||
|
|
|
|||
|
|
@ -1614,6 +1614,7 @@ fn authenticate(ptr: *anyopaque) !bool {
|
|||
.xauth_cmd = state.config.xauth_cmd,
|
||||
.setup_cmd = state.config.setup_cmd,
|
||||
.login_cmd = state.config.login_cmd,
|
||||
.faillock_tally_dir = state.config.faillock_tally_dir,
|
||||
.x_cmd = state.config.x_cmd,
|
||||
.x_vt = state.config.x_vt,
|
||||
.session_pid = session_pid,
|
||||
|
|
@ -2641,6 +2642,7 @@ fn getAuthErrorMsg(err: anyerror, lang: Lang) []const u8 {
|
|||
error.PamSystemError => lang.err_pam_sys,
|
||||
error.PamUserUnknown => lang.err_pam_user_unknown,
|
||||
error.PamAbort => lang.err_pam_abort,
|
||||
error.AccountLocked => lang.err_acc_locked,
|
||||
else => @errorName(err),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue