From c20857850f34203d29757eb6844905074c59825a Mon Sep 17 00:00:00 2001 From: Tristan Ross Date: Mon, 29 Apr 2024 19:53:34 -0700 Subject: [PATCH] feat: working on unlocking --- flake.nix | 6 ++++- lib/views/system/lock.dart | 25 +++++++++++++++++--- linux/CMakeLists.txt | 3 +++ linux/channels/auth.cc | 48 +++++++++++++++----------------------- linux/data/pam | 5 ++++ nix/module.nix | 2 ++ 6 files changed, 56 insertions(+), 33 deletions(-) create mode 100644 linux/data/pam diff --git a/flake.nix b/flake.nix index dfd9ca0f..80cdc81c 100644 --- a/flake.nix +++ b/flake.nix @@ -29,8 +29,12 @@ pubspecLock = lib.importJSON ./pubspec.lock.json; + postInstall = '' + mv $out/bin/genesis_shell $out/bin/genesis-shell + ''; + meta = { - mainProgram = "genesis_shell"; + mainProgram = "genesis-shell"; }; }; }; diff --git a/lib/views/system/lock.dart b/lib/views/system/lock.dart index 8b7dfc27..25bbcc4b 100644 --- a/lib/views/system/lock.dart +++ b/lib/views/system/lock.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart'; import 'package:intl/intl.dart'; @@ -15,11 +16,27 @@ class SystemLockView extends StatefulWidget { } class _SystemLockViewState extends State { + static const platform = MethodChannel('com.expidusos.genesis.shell/auth'); + TextEditingController passcodeController = TextEditingController(); + String? errorText = null; void _onSubmitted(String input) { - passcodeController.clear(); - print(input); + setState(() { + errorText = null; + }); + + platform.invokeMethod('auth', { + 'password': input, + }).then((user) { + setState(() { + passcodeController.clear(); + errorText = null; + }); + print(user); + }).catchError((err) => setState(() { + errorText = '${err.code}: ${err.message}: ${err.details.toString()}'; + })); } @override @@ -98,9 +115,11 @@ class _SystemLockViewState extends State { child: TextField( controller: passcodeController, obscureText: true, - decoration: const InputDecoration( + decoration: InputDecoration( border: OutlineInputBorder(), contentPadding: EdgeInsets.symmetric(horizontal: 4.0), + errorMaxLines: 5, + errorText: errorText, ), style: Theme.of(context).textTheme.displayMedium, onSubmitted: _onSubmitted, diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 0a18e7ba..fb1c4bfa 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -120,6 +120,9 @@ install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR} install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime) +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/data/pam" DESTINATION "${CMAKE_INSTALL_PREFIX}/etc/pam.d" + RENAME "genesis-shell") + foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) install(FILES "${bundled_library}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" diff --git a/linux/channels/auth.cc b/linux/channels/auth.cc index 549d9fc2..95fe895c 100644 --- a/linux/channels/auth.cc +++ b/linux/channels/auth.cc @@ -3,55 +3,45 @@ #include #include +#include + #include "outputs.h" #include "../application-priv.h" -static void message_callback(GObject* obj, GAsyncResult* result, gpointer user_data) { - GArray* array_resp = (GArray*)user_data; - - g_autoptr(FlMethodResponse) response = fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(obj), result, nullptr); - g_autoptr(FlValue) resp_value = fl_method_response_get_result(response, nullptr); - - struct pam_response resp; - resp.resp_retcode = 0; - resp.resp = g_strdup(fl_value_get_string(resp_value)); - g_array_append_val(array_resp, resp); -} - static int conversation(int num_msg, const struct pam_message** msg, struct pam_response** resp, void* appdata_ptr) { - GenesisShellApplication* self = GENESIS_SHELL_APPLICATION(appdata_ptr); - - GArray* array_resp = g_array_new(false, true, sizeof (struct pam_response)); - + struct pam_response* array_resp = (struct pam_response*)malloc(num_msg * sizeof(struct pam_response)); for (int i = 0; i < num_msg; i++) { - const char* msg_content = msg[i]->msg; - - fl_method_channel_invoke_method(self->auth, "ask", fl_value_new_string(msg_content), nullptr, message_callback, array_resp); - } - - while (true) { - if ((array_resp->len / sizeof (struct pam_response)) == num_msg) { - break; - } + array_resp[i].resp_retcode = 0; + array_resp[i].resp = g_strdup((const gchar*)appdata_ptr); } - *resp = static_cast(g_array_steal(array_resp, nullptr)); + *resp = array_resp; return PAM_SUCCESS; } void auth_method_call_handler(FlMethodChannel* channel, FlMethodCall* method_call, gpointer user_data) { g_autoptr(FlMethodResponse) response = nullptr; - if (strcmp(fl_method_call_get_name(method_call), "start") == 0) { + if (strcmp(fl_method_call_get_name(method_call), "auth") == 0) { FlValue* args = fl_method_call_get_args(method_call); gchar* username = nullptr; if (fl_value_lookup_string(args, "username") != nullptr) { username = (gchar*)fl_value_get_string(fl_value_lookup_string(args, "username")); + } else { + struct passwd* pw = nullptr; + if ((pw = getpwuid(getuid())) == NULL) { + fl_method_call_respond_error(method_call, "shadow", "failed to get the username", NULL, NULL); + return; + } + + username = pw->pw_name; } + const gchar* password = fl_value_get_string(fl_value_lookup_string(args, "password")); + struct pam_conv* conv = (struct pam_conv*)malloc(sizeof(struct pam_conv)); conv->conv = conversation; - conv->appdata_ptr = user_data; + conv->appdata_ptr = (void*)password; pam_handle_t* handle = NULL; int r = pam_start("genesis-shell", username, conv, &handle); @@ -70,7 +60,7 @@ void auth_method_call_handler(FlMethodChannel* channel, FlMethodCall* method_cal return; } - r = pam_acct_mgmt(handle, PAM_SILENT); + r = pam_setcred(handle, PAM_REFRESH_CRED); if (r != PAM_SUCCESS) { fl_method_call_respond_error(method_call, "PAM", "pam_acct_mgmt failed", fl_value_new_string(pam_strerror(handle, r)), NULL); pam_end(handle, r); diff --git a/linux/data/pam b/linux/data/pam new file mode 100644 index 00000000..11b84fdb --- /dev/null +++ b/linux/data/pam @@ -0,0 +1,5 @@ +# Genesis Shell login management + +auth required pam_unix.so +account required pam_unix.so +password required pam_unix.so diff --git a/nix/module.nix b/nix/module.nix index 0324992b..e9adfe51 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -11,6 +11,8 @@ isNormalUser = true; }; + security.pam.services.genesis-shell = {}; + nix.enable = false; system.stateVersion = lib.version;