mirror of
https://github.com/fairyglade/ly.git
synced 2025-12-20 19:24:53 +00:00
Fix processing wrt fingerprint login
This also involves a major split of the authentication code, which allows the fingerprint and password logins to use the same code.
This commit is contained in:
130
src/auth.zig
130
src/auth.zig
@@ -23,17 +23,10 @@ pub fn sessionSignalHandler(i: c_int) callconv(.C) void {
|
||||
if (child_pid > 0) _ = std.c.kill(child_pid, i);
|
||||
}
|
||||
|
||||
pub fn authenticate(config: Config, current_environment: Session.Environment, login: [:0]const u8, password: [:0]const u8) !void {
|
||||
var tty_buffer: [3]u8 = undefined;
|
||||
const tty_str = try std.fmt.bufPrintZ(&tty_buffer, "{d}", .{config.tty});
|
||||
|
||||
pub fn authenticate(config: Config, login: [:0]const u8, password: [:0]const u8) !*interop.pam.pam_handle {
|
||||
var pam_tty_buffer: [6]u8 = undefined;
|
||||
const pam_tty_str = try std.fmt.bufPrintZ(&pam_tty_buffer, "tty{d}", .{config.tty});
|
||||
|
||||
// Set the XDG environment variables
|
||||
setXdgSessionEnv(current_environment.display_server);
|
||||
try setXdgEnv(tty_str, current_environment.xdg_session_desktop orelse "", current_environment.xdg_desktop_names orelse "");
|
||||
|
||||
// Open the PAM session
|
||||
var credentials = [_:null]?[*:0]const u8{ login, password };
|
||||
|
||||
@@ -43,15 +36,15 @@ pub fn authenticate(config: Config, current_environment: Session.Environment, lo
|
||||
};
|
||||
var handle: ?*interop.pam.pam_handle = undefined;
|
||||
|
||||
// Do the PAM routine
|
||||
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);
|
||||
errdefer interop.pam.pam_end(handle, status);
|
||||
|
||||
// Set PAM_TTY as the current TTY. This is required in case it isn't being set by another PAM module
|
||||
status = interop.pam.pam_set_item(handle, interop.pam.PAM_TTY, pam_tty_str.ptr);
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
|
||||
// Do the PAM routine
|
||||
status = interop.pam.pam_authenticate(handle, 0);
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
|
||||
@@ -59,12 +52,27 @@ pub fn authenticate(config: Config, current_environment: Session.Environment, lo
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
|
||||
status = interop.pam.pam_setcred(handle, interop.pam.PAM_ESTABLISH_CRED);
|
||||
defer {
|
||||
if (status != interop.pam.PAM_SUCCESS) _ = interop.pam.pam_end(handle, status);
|
||||
}
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
return handle.?;
|
||||
}
|
||||
|
||||
pub fn finaliseAuth(config: Config, current_environment: Session.Environment, handle: ?*interop.pam.pam_handle, login: [:0]const u8) !void {
|
||||
var tty_buffer: [2]u8 = undefined;
|
||||
const tty_str = try std.fmt.bufPrintZ(&tty_buffer, "{d}", .{config.tty});
|
||||
|
||||
// Close the PAM session
|
||||
var status = interop.pam.pam_open_session(handle, 0);
|
||||
defer status = interop.pam.pam_close_session(handle, status);
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
defer status = interop.pam.pam_setcred(handle, interop.pam.PAM_DELETE_CRED);
|
||||
defer status = interop.pam.pam_end(handle, status);
|
||||
|
||||
status = interop.pam.pam_open_session(handle, 0);
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
defer status = interop.pam.pam_close_session(handle, 0);
|
||||
// Set the XDG environment variables
|
||||
setXdgSessionEnv(current_environment.display_server);
|
||||
try setXdgEnv(tty_str, current_environment.xdg_session_desktop orelse "", current_environment.xdg_desktop_names orelse "");
|
||||
|
||||
var pwd: *interop.pwd.passwd = undefined;
|
||||
{
|
||||
@@ -120,102 +128,6 @@ pub fn authenticate(config: Config, current_environment: Session.Environment, lo
|
||||
if (shared_err.readError()) |err| return err;
|
||||
}
|
||||
|
||||
pub fn fingerprintAuth(config: Config, login: [:0]const u8) !*interop.pam.pam_handle {
|
||||
// Open the PAM session
|
||||
var credentials = [_:null]?[*:0]const u8{ login, "" };
|
||||
|
||||
const conv = interop.pam.pam_conv{
|
||||
.conv = loginConv,
|
||||
.appdata_ptr = @ptrCast(&credentials),
|
||||
};
|
||||
var handle: ?*interop.pam.pam_handle = undefined;
|
||||
|
||||
var status = interop.pam.pam_start(config.service_name.ptr, null, &conv, &handle);
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
|
||||
// Do the PAM routine
|
||||
status = interop.pam.pam_authenticate(handle, 0);
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
|
||||
status = interop.pam.pam_acct_mgmt(handle, 0);
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
|
||||
status = interop.pam.pam_setcred(handle, interop.pam.PAM_ESTABLISH_CRED);
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
|
||||
status = interop.pam.pam_open_session(handle, 0);
|
||||
if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status);
|
||||
|
||||
return handle.?;
|
||||
}
|
||||
|
||||
pub fn postFingerprintAuth(config: Config, desktop: Desktop, handle: *interop.pam.pam_handle, login: [:0]const u8) !void {
|
||||
var tty_buffer: [2]u8 = undefined;
|
||||
const tty_str = try std.fmt.bufPrintZ(&tty_buffer, "{d}", .{config.tty});
|
||||
const current_environment = desktop.environments.items[desktop.current];
|
||||
|
||||
// Set the XDG environment variables
|
||||
setXdgSessionEnv(current_environment.display_server);
|
||||
try setXdgEnv(tty_str, current_environment.xdg_session_desktop, current_environment.xdg_desktop_names orelse "");
|
||||
|
||||
var pwd: *interop.passwd = undefined;
|
||||
{
|
||||
defer interop.endpwent();
|
||||
|
||||
// Get password structure from username
|
||||
pwd = interop.getpwnam(login.ptr) orelse return error.GetPasswordNameFailed;
|
||||
}
|
||||
|
||||
// Set user shell if it hasn't already been set
|
||||
if (pwd.pw_shell[0] == 0) {
|
||||
interop.setusershell();
|
||||
pwd.pw_shell = interop.getusershell();
|
||||
interop.endusershell();
|
||||
}
|
||||
|
||||
var shared_err = try SharedError.init();
|
||||
defer shared_err.deinit();
|
||||
|
||||
child_pid = try std.posix.fork();
|
||||
if (child_pid == 0) {
|
||||
startSession(config, pwd, handle, current_environment) catch |e| {
|
||||
shared_err.writeError(e);
|
||||
std.process.exit(1);
|
||||
};
|
||||
std.process.exit(0);
|
||||
}
|
||||
|
||||
var entry: Utmp = std.mem.zeroes(Utmp);
|
||||
addUtmpEntry(&entry, pwd.pw_name, child_pid) catch {};
|
||||
|
||||
// If we receive SIGTERM, forward it to child_pid
|
||||
const act = std.posix.Sigaction{
|
||||
.handler = .{ .handler = &sessionSignalHandler },
|
||||
.mask = std.posix.empty_sigset,
|
||||
.flags = 0,
|
||||
};
|
||||
try std.posix.sigaction(std.posix.SIG.TERM, &act, null);
|
||||
|
||||
// Wait for the session to stop
|
||||
_ = std.posix.waitpid(child_pid, 0);
|
||||
|
||||
removeUtmpEntry(&entry);
|
||||
|
||||
try resetTerminal(pwd.pw_shell, config.term_reset_cmd);
|
||||
|
||||
// Close the PAM session
|
||||
var status = interop.pam.pam_close_session(handle, 0);
|
||||
if (status != 0) return pamDiagnose(status);
|
||||
|
||||
status = interop.pam.pam_setcred(handle, interop.pam.PAM_DELETE_CRED);
|
||||
if (status != 0) return pamDiagnose(status);
|
||||
|
||||
status = interop.pam.pam_end(handle, status);
|
||||
if (status != 0) return pamDiagnose(status);
|
||||
|
||||
if (shared_err.readError()) |err| return err;
|
||||
}
|
||||
|
||||
fn startSession(
|
||||
config: Config,
|
||||
pwd: *interop.pwd.passwd,
|
||||
|
||||
66
src/main.zig
66
src/main.zig
@@ -45,7 +45,7 @@ var asyncPamHandle: ?*interop.pam.pam_handle = null;
|
||||
|
||||
fn fingerprintLogin(config: Config, login: [:0]const u8) !void {
|
||||
// TODO: loop if there was an error
|
||||
const pamHandle = try auth.fingerprintAuth(config, login);
|
||||
const pamHandle = try auth.authenticate(config, login, "");
|
||||
if (currentLogin != null and !std.mem.eql(u8, std.mem.span(@as([*:0]const u8, currentLogin.?)), login)) {
|
||||
return;
|
||||
}
|
||||
@@ -594,18 +594,49 @@ pub fn main() !void {
|
||||
const event_error = termbox.tb_peek_event(&event, @intCast(@min(timeoutEnd - std.time.milliTimestamp(), maxtimeout)));
|
||||
|
||||
if (asyncPamHandle) |handle| {
|
||||
if (auth.postFingerprintAuth(config, session, handle, currentLogin.?)) |_| {
|
||||
try info_line.setText(lang.logout);
|
||||
} else |err| {
|
||||
active_input = .password;
|
||||
try info_line.setText(getAuthErrorMsg(err, lang));
|
||||
try startFingerPrintLogin(allocator, config, login);
|
||||
var shared_err = try SharedError.init();
|
||||
defer shared_err.deinit();
|
||||
|
||||
{
|
||||
const login_text = try allocator.dupeZ(u8, login.text.items);
|
||||
defer allocator.free(login_text);
|
||||
|
||||
InfoLine.clearRendered(allocator, buffer) catch {};
|
||||
info_line.draw(buffer);
|
||||
_ = termbox.tb_present();
|
||||
|
||||
session_pid = try std.posix.fork();
|
||||
if (session_pid == 0) {
|
||||
const current_environment = session.environments.items[session.current];
|
||||
auth.finaliseAuth(config, current_environment, handle, login_text) catch |err| {
|
||||
shared_err.writeError(err);
|
||||
std.process.exit(1);
|
||||
};
|
||||
|
||||
std.process.exit(0);
|
||||
}
|
||||
_ = std.posix.waitpid(session_pid, 0);
|
||||
|
||||
session_pid = -1;
|
||||
}
|
||||
|
||||
const auth_err = shared_err.readError();
|
||||
if (auth_err) |err| {
|
||||
try info_line.setText(getAuthErrorMsg(err, lang));
|
||||
} else {
|
||||
try info_line.setText(lang.logout);
|
||||
}
|
||||
asyncPamHandle = null;
|
||||
try startFingerPrintLogin(allocator, config, login);
|
||||
|
||||
try std.posix.tcsetattr(std.posix.STDIN_FILENO, .FLUSH, tb_termios);
|
||||
_ = termbox.tb_clear();
|
||||
_ = termbox.tb_present();
|
||||
|
||||
update = true;
|
||||
|
||||
var restore_cursor = std.process.Child.init(&[_][]const u8{ "/bin/sh", "-c", config.term_restore_cursor_cmd }, allocator);
|
||||
_ = restore_cursor.spawnAndWait() catch .{};
|
||||
}
|
||||
skipEvent = event_error < 0;
|
||||
if ((event_error < 0 and event_error != -6) or event.type == termbox.TB_EVENT_KEY) break;
|
||||
@@ -721,16 +752,21 @@ pub fn main() !void {
|
||||
_ = termbox.tb_shutdown();
|
||||
|
||||
session_pid = try std.posix.fork();
|
||||
if (session_pid == 0) {
|
||||
const current_environment = session.label.list.items[session.label.current];
|
||||
auth.authenticate(config, current_environment, login_text, password_text) catch |err| {
|
||||
shared_err.writeError(err);
|
||||
std.process.exit(1);
|
||||
};
|
||||
std.process.exit(0);
|
||||
const current_environment = session.environments.items[session.current];
|
||||
if (auth.authenticate(config, login_text, password_text)) |handle| {
|
||||
if (session_pid == 0) {
|
||||
auth.finaliseAuth(config, current_environment, handle, login_text) catch |err| {
|
||||
shared_err.writeError(err);
|
||||
std.process.exit(1);
|
||||
};
|
||||
|
||||
std.process.exit(0);
|
||||
}
|
||||
_ = std.posix.waitpid(session_pid, 0);
|
||||
} else |err| {
|
||||
shared_err.writeError(err);
|
||||
}
|
||||
|
||||
_ = std.posix.waitpid(session_pid, 0);
|
||||
session_pid = -1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user