From 1cf55952084b6b47c1a2bda2a3791614965f52f8 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Fri, 2 Jul 2021 13:26:05 +0100 Subject: [PATCH] auth and desklock - support auth by fingerprint and show status --- src/bin/e_auth.c | 339 ++++++++++++++++++++++++++++++++++++ src/bin/e_auth.h | 38 ++++ src/bin/e_main.c | 5 + src/bin/e_utils.c | 9 + src/bin/e_utils.h | 2 + src/modules/lokker/lokker.c | 64 +++++++ 6 files changed, 457 insertions(+) diff --git a/src/bin/e_auth.c b/src/bin/e_auth.c index 0ab534511..e18a868f4 100644 --- a/src/bin/e_auth.c +++ b/src/bin/e_auth.c @@ -1,5 +1,32 @@ #include "e.h" +E_API int E_EVENT_AUTH_FPRINT_AVAILABLE = 0; +E_API int E_EVENT_AUTH_FPRINT_STATUS = 0; + +static Eldbus_Connection *conn = NULL; + +///////////////////////////////////////////////////////////////////////////// + +EINTERN int +e_auth_init(void) +{ + E_EVENT_AUTH_FPRINT_AVAILABLE = ecore_event_type_new(); + E_EVENT_AUTH_FPRINT_STATUS = ecore_event_type_new(); + + conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM); + return 1; +} + +EINTERN int +e_auth_shutdown(void) +{ + if (conn) eldbus_connection_unref(conn); + conn = NULL; + return 1; +} + +///////////////////////////////////////////////////////////////////////////// + E_API int e_auth_begin(char *passwd) { @@ -72,3 +99,315 @@ out: e_util_memclear(buf, buflen); return ret; } + +///////////////////////////////////////////////////////////////////////////// + +static Eldbus_Object *obj_fprint = NULL; +static Eldbus_Proxy *proxy_fprint = NULL; + +static Eldbus_Object *obj_fprint_device = NULL; +static Eldbus_Proxy *proxy_fprint_device = NULL; +static E_Auth_Fprint_Type finger_type = E_AUTH_FPRINT_TYPE_UNKNOWN; +static const char *finger_name = NULL; +static const char *user_name = NULL; + +static void +_cb_event_free(void *data EINA_UNUSED, void *event) +{ + free(event); +} + +static void +_cb_verify_start(void *data EINA_UNUSED, const Eldbus_Message *m, + Eldbus_Pending *p EINA_UNUSED) +{ + const char *name = NULL, *text = NULL; + + printf("FP: verify start...\n"); + if (eldbus_message_error_get(m, &name, &text)) + { + fprintf(stderr, "Fprint err: %s %s\n", name, text); + return; + } +} + +static void +_verify_begin(void) +{ + Eldbus_Message *m2; + Eldbus_Message_Iter *iter; + + // brute force stop a previous verify - if its active - dont care about reply + m2 = eldbus_proxy_method_call_new(proxy_fprint_device, "VerifyStop"); + if (m2) + { + eldbus_proxy_send(proxy_fprint_device, m2, NULL, NULL, -1); + } + m2 = eldbus_proxy_method_call_new(proxy_fprint_device, "VerifyStart"); + if (m2) + { + iter = eldbus_message_iter_get(m2); + eldbus_message_iter_basic_append(iter, 's', finger_name); + eldbus_proxy_send(proxy_fprint_device, m2, _cb_verify_start, NULL, -1); + } +} + +static void +_cb_verify(void *data EINA_UNUSED, const Eldbus_Message *m) +{ + Eina_Bool val = EINA_FALSE; + const char *txt = NULL; + const char *name = NULL, *text = NULL; + E_Event_Auth_Fprint_Status *ev; + + printf("FP: verify ...\n"); + if (eldbus_message_error_get(m, &name, &text)) + { + fprintf(stderr, "Fprint err: %s %s\n", name, text); + return; + } + if (!eldbus_message_arguments_get(m, "sb", &txt, &val)) return; + printf("FP: verify = [%s] %i\n", txt, val); + if (!txt) return; + + ev = calloc(1, sizeof(E_Event_Auth_Fprint_Status)); + if (!ev) return; + + if (!strcmp(txt, "verify-match")) ev->status = E_AUTH_FPRINT_STATUS_AUTH; + else if (!strcmp(txt, "verify-no-match")) ev->status = E_AUTH_FPRINT_STATUS_NO_AUTH; + else if (!strcmp(txt, "verify-swipe-too-short")) ev->status = E_AUTH_FPRINT_STATUS_SHORT_SWIPE; + else if (!strcmp(txt, "verify-finger-not-centered")) ev->status = E_AUTH_FPRINT_STATUS_NO_CENTER; + else if (!strcmp(txt, "verify-remove-and-retry")) ev->status = E_AUTH_FPRINT_STATUS_REMOVE_RETRY; + else if (!strcmp(txt, "verify-retry-scan")) ev->status = E_AUTH_FPRINT_STATUS_RETRY; + else if (!strcmp(txt, "verify-disconnected")) ev->status = E_AUTH_FPRINT_STATUS_DISCONNECT; + else if (!strcmp(txt, "verify-unknown-error")) ev->status = E_AUTH_FPRINT_STATUS_ERROR; + else ev->status = E_AUTH_FPRINT_STATUS_ERROR; + ecore_event_add(E_EVENT_AUTH_FPRINT_STATUS, ev, _cb_event_free, NULL); + // reset the verify and try again if verify end and NOT an auth ok + if ((val) && // end of verify + (ev->status != E_AUTH_FPRINT_STATUS_AUTH)) + { + _verify_begin(); + } + if (ev->status == E_AUTH_FPRINT_STATUS_AUTH) + { + Eldbus_Message *m2; + + m2 = eldbus_proxy_method_call_new(proxy_fprint_device, "Release"); + eldbus_proxy_send(proxy_fprint_device, m2, NULL, NULL, -1); + } +} + +static void +_cb_list_enrolled_fingers(void *data EINA_UNUSED, const Eldbus_Message *m, + Eldbus_Pending *p EINA_UNUSED) +{ + Eldbus_Message_Iter *array = NULL; + const char *name = NULL, *text = NULL; + + printf("FP: list fingers...\n"); + if (eldbus_message_error_get(m, &name, &text)) + { + fprintf(stderr, "Fprint err: %s %s\n", name, text); + return; + } + printf("FP: list fingers...\n"); + if (eldbus_message_arguments_get(m, "as", &array)) + { + char *txt = NULL; + + printf("FP: ...\n"); + while (eldbus_message_iter_get_and_next(array, 's', &txt)) + { + eina_stringshare_replace(&finger_name, txt); + printf("FP: first finger is [%s]\n", txt); + if (finger_type != E_AUTH_FPRINT_TYPE_UNKNOWN) + { + E_Event_Auth_Fprint_Available *ev = calloc(1, sizeof(E_Event_Auth_Fprint_Available)); + if (ev) + { + ev->type = finger_type; + ecore_event_add(E_EVENT_AUTH_FPRINT_AVAILABLE, ev, + _cb_event_free, NULL); + } + } + _verify_begin(); + break; + } + // call VeriftyStart 'first finger found' + } +} + +static void +_cb_claim(void *data EINA_UNUSED, const Eldbus_Message *m EINA_UNUSED, + Eldbus_Pending *p EINA_UNUSED) +{ + Eldbus_Proxy *proxy = proxy_fprint_device; + Eldbus_Message *m2; + Eldbus_Message_Iter *iter; + const char *name = NULL, *text = NULL; + + printf("FP: claim\n"); + if (eldbus_message_error_get(m, &name, &text)) + { + fprintf(stderr, "Fprint err: %s %s\n", name, text); + return; + } + // ListEnrolledFingrs '$USER' -> "as" + printf("FP: claim ok\n"); + m2 = eldbus_proxy_method_call_new(proxy, "ListEnrolledFingers"); + iter = eldbus_message_iter_get(m2); + eldbus_message_iter_basic_append(iter, 's', user_name); + eldbus_proxy_send(proxy, m2, _cb_list_enrolled_fingers, NULL, -1); +} + +static void +_cb_prop_entry(void *data EINA_UNUSED, const void *key, Eldbus_Message_Iter *var) +{ + const char *skey = key; + + if (!strcmp(skey, "scan-type")) + { + const char *val = NULL; + if (eldbus_message_iter_arguments_get(var, "s", &val)) + { + if (!strcmp(val, "press")) finger_type = E_AUTH_FPRINT_TYPE_PRESS; + else if (!strcmp(val, "swipe")) finger_type = E_AUTH_FPRINT_TYPE_SWIPE; + printf("FP: type = %s\n", val); + if (finger_name) + { + E_Event_Auth_Fprint_Available *ev = + calloc(1, sizeof(E_Event_Auth_Fprint_Available)); + if (ev) + { + ev->type = finger_type; + ecore_event_add(E_EVENT_AUTH_FPRINT_AVAILABLE, ev, + _cb_event_free, NULL); + } + } + } + } +} + +static void +_cb_props(void *data EINA_UNUSED, const Eldbus_Message *m, + Eldbus_Pending *pending EINA_UNUSED) +{ + Eldbus_Message_Iter *array = NULL; + + if (eldbus_message_error_get(m, NULL, NULL)) return; + + if (eldbus_message_arguments_get(m, "a{sv}", &array)) + eldbus_message_iter_dict_iterate(array, "sv", _cb_prop_entry, NULL); +} + +static void +_cb_get_default_device(void *data EINA_UNUSED, const Eldbus_Message *m, + Eldbus_Pending *p EINA_UNUSED) +{ + Eldbus_Object *obj; + Eldbus_Proxy *proxy; + const char *dev = NULL; + const char *name = NULL, *text = NULL; + + printf("FP: get default device...\n"); + if (eldbus_message_error_get(m, &name, &text)) + { + fprintf(stderr, "Fprint err: %s %s\n", name, text); + return; + } + if (!eldbus_message_arguments_get(m, "o", &dev)) return; + printf("FP: dev = %s\n", dev); + obj = eldbus_object_get(conn, "net.reactivated.Fprint", dev); + if (obj) + { + obj_fprint_device = obj; + + printf("FP: 22 obj = %p\n", obj); + proxy = eldbus_proxy_get(obj, "net.reactivated.Fprint.Device"); + if (proxy) + { + Eldbus_Message *m2; + Eldbus_Message_Iter *iter; + + printf("FP: 22 proxy = %p\n", proxy); + proxy_fprint_device = proxy; + + eldbus_proxy_property_get_all(proxy, _cb_props, NULL); + + eldbus_proxy_signal_handler_add(proxy, "VerifyStatus", + _cb_verify, NULL); + // Claim '$USER' + m2 = eldbus_proxy_method_call_new(proxy, "Claim"); + iter = eldbus_message_iter_get(m2); + eldbus_message_iter_basic_append(iter, 's', user_name); + eldbus_proxy_send(proxy, m2, _cb_claim, NULL, -1); + } + } +} + +E_API void +e_auth_fprint_begin(const char *user) +{ + Eldbus_Object *obj; + Eldbus_Proxy *proxy; + + printf("FP: e_auth_fprint_begin\n"); + if (conn) + { + eina_stringshare_replace(&user_name, user); + obj = eldbus_object_get(conn, "net.reactivated.Fprint", + "/net/reactivated/Fprint/Manager"); + printf("FP: obj=%p\n", obj); + if (obj) + { + obj_fprint = obj; + + proxy = eldbus_proxy_get(obj, "net.reactivated.Fprint.Manager"); + printf("FP: proxy=%p\n", proxy); + if (proxy) + { + Eldbus_Message *m; + + proxy_fprint = proxy; + m = eldbus_proxy_method_call_new(proxy, "GetDefaultDevice"); + eldbus_proxy_send(proxy, m, _cb_get_default_device, NULL, -1); + } + } + } +} + +E_API void +e_auth_fprint_end(void) +{ + if (conn) + { + if (obj_fprint_device) + { + Eldbus_Message *m2; + + m2 = eldbus_proxy_method_call_new(proxy_fprint_device, "Release"); + eldbus_proxy_send(proxy_fprint_device, m2, NULL, NULL, -1); + if (proxy_fprint_device) + { + eldbus_proxy_unref(proxy_fprint_device); + proxy_fprint_device = NULL; + } + eldbus_object_unref(obj_fprint_device); + obj_fprint_device = NULL; + } + if (obj_fprint) + { + if (proxy_fprint) + { + eldbus_proxy_unref(proxy_fprint); + proxy_fprint = NULL; + } + eldbus_object_unref(obj_fprint); + obj_fprint = NULL; + } + } + eina_stringshare_replace(&finger_name, NULL); + eina_stringshare_replace(&user_name, NULL); + finger_type = E_AUTH_FPRINT_TYPE_UNKNOWN; +} diff --git a/src/bin/e_auth.h b/src/bin/e_auth.h index 8728f2900..85ec13816 100644 --- a/src/bin/e_auth.h +++ b/src/bin/e_auth.h @@ -1,6 +1,41 @@ #ifndef E_AUTH_H #define E_AUTH_H +typedef enum _E_Auth_Fprint_Type +{ + E_AUTH_FPRINT_TYPE_UNKNOWN, + E_AUTH_FPRINT_TYPE_PRESS, + E_AUTH_FPRINT_TYPE_SWIPE +} E_Auth_Fprint_Type; + +typedef enum _E_Auth_Fprint_Status +{ + E_AUTH_FPRINT_STATUS_AUTH, + E_AUTH_FPRINT_STATUS_NO_AUTH, + E_AUTH_FPRINT_STATUS_SHORT_SWIPE, + E_AUTH_FPRINT_STATUS_NO_CENTER, + E_AUTH_FPRINT_STATUS_REMOVE_RETRY, + E_AUTH_FPRINT_STATUS_RETRY, + E_AUTH_FPRINT_STATUS_DISCONNECT, + E_AUTH_FPRINT_STATUS_ERROR +} E_Auth_Fprint_Status; + +typedef struct _E_Event_Auth_Fprint_Available +{ + E_Auth_Fprint_Type type; +} E_Event_Auth_Fprint_Available; + +typedef struct _E_Event_Auth_Fprint_Status +{ + E_Auth_Fprint_Status status; +} E_Event_Auth_Fprint_Status; + +extern E_API int E_EVENT_AUTH_FPRINT_AVAILABLE; +extern E_API int E_EVENT_AUTH_FPRINT_STATUS; + +EINTERN int e_auth_init(void); +EINTERN int e_auth_shutdown(void); + E_API int e_auth_begin(char *passwd); E_API int e_auth_polkit_begin(char *passwd, const char *cookie, unsigned int uid); @@ -17,4 +52,7 @@ e_auth_hash_djb2(const char *key, int len) return (int)hash_num; } +E_API void e_auth_fprint_begin(const char *user); +E_API void e_auth_fprint_end(void); + #endif diff --git a/src/bin/e_main.c b/src/bin/e_main.c index a4a12fbaa..68ed3507a 100644 --- a/src/bin/e_main.c +++ b/src/bin/e_main.c @@ -859,6 +859,11 @@ main(int argc, char **argv) TS("E_Acpi Init Done"); _e_main_shutdown_push(e_acpi_shutdown); + TS("E_Auth Init"); + e_auth_init(); + TS("E_Auth Init Done"); + _e_main_shutdown_push(e_auth_shutdown); + TS("E_Backlight Init"); if (!e_backlight_init()) { diff --git a/src/bin/e_utils.c b/src/bin/e_utils.c index 49716ebdd..637579fc9 100644 --- a/src/bin/e_utils.c +++ b/src/bin/e_utils.c @@ -1557,3 +1557,12 @@ e_util_key_geometry_action_get(const char *key, int *x, int *y, int dx, int dy) return E_UTIL_ACTION_DO; } + +E_API const char * +e_username_get(void) +{ + struct passwd *pw = getpwuid(getuid()); + + if (pw) return pw->pw_name; + return ""; +} diff --git a/src/bin/e_utils.h b/src/bin/e_utils.h index eac3cfb6d..8884ede03 100644 --- a/src/bin/e_utils.h +++ b/src/bin/e_utils.h @@ -70,6 +70,8 @@ E_API Ecore_Exe *e_util_open(const char *exe, void *data); E_API Ecore_Exe *e_util_exe_safe_run(const char *cmd, void *data); +E_API const char *e_username_get(void); + typedef enum { E_UTIL_ACTION_NONE, diff --git a/src/modules/lokker/lokker.c b/src/modules/lokker/lokker.c index 36dc77597..c864810cd 100644 --- a/src/modules/lokker/lokker.c +++ b/src/modules/lokker/lokker.c @@ -741,6 +741,64 @@ _lokker_check_auth(void) return 0; } +static Eina_Bool +_lokker_cb_fprint_available(void *data EINA_UNUSED, + int type EINA_UNUSED, + void *event) +{ + E_Event_Auth_Fprint_Available *ev = event; + Lokker_Popup *lp; + Eina_List *l; + const char *sig = ""; + + if (!edd) return ECORE_CALLBACK_PASS_ON; + + if (ev->type == E_AUTH_FPRINT_TYPE_UNKNOWN) sig = "e,fprint,unknown"; + else if (ev->type == E_AUTH_FPRINT_TYPE_PRESS) sig = "e,fprint,press"; + else if (ev->type == E_AUTH_FPRINT_TYPE_SWIPE) sig = "e,fprint,swipe"; + EINA_LIST_FOREACH(edd->elock_wnd_list, l, lp) + { + if (lp->login_box) edje_object_signal_emit(lp->login_box, sig, "e"); + if (lp->bg_object) edje_object_signal_emit(lp->bg_object, sig, "e"); + } + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_lokker_cb_fprint_status(void *data EINA_UNUSED, + int type EINA_UNUSED, + void *event) +{ + E_Event_Auth_Fprint_Status *ev = event; + Lokker_Popup *lp; + Eina_List *l; + const char *sig = ""; + + if (!edd) return ECORE_CALLBACK_PASS_ON; + + if (ev->status == E_AUTH_FPRINT_STATUS_AUTH) sig = "e,fprint,auth,succeed"; + else if (ev->status == E_AUTH_FPRINT_STATUS_NO_AUTH) sig = "e,fprint,auth,fail"; + else if (ev->status == E_AUTH_FPRINT_STATUS_SHORT_SWIPE) sig = "e,fprint,auth,short"; + else if (ev->status == E_AUTH_FPRINT_STATUS_NO_CENTER) sig = "e,fprint,auth,nocenter"; + else if (ev->status == E_AUTH_FPRINT_STATUS_REMOVE_RETRY) sig = "e,fprint,auth,removeretry"; + else if (ev->status == E_AUTH_FPRINT_STATUS_RETRY) sig = "e,fprint,auth,retry"; + else if (ev->status == E_AUTH_FPRINT_STATUS_DISCONNECT) sig = "e,fprint,auth,disconnect"; + else if (ev->status == E_AUTH_FPRINT_STATUS_ERROR) sig = "e,fprint,auth,error"; + + EINA_LIST_FOREACH(edd->elock_wnd_list, l, lp) + { + if (lp->login_box) edje_object_signal_emit(lp->login_box, sig, "e"); + if (lp->bg_object) edje_object_signal_emit(lp->bg_object, sig, "e"); + } + if (ev->status == E_AUTH_FPRINT_STATUS_AUTH) + { + /* security - null out passwd string once we are done with it */ + _lokker_null(); + e_desklock_hide(); + } + return ECORE_CALLBACK_PASS_ON; +} + EINTERN Eina_Bool lokker_key_up(Ecore_Event_Key *ev) { @@ -875,12 +933,18 @@ lokker_lock(void) edd->move_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, _lokker_cb_mouse_move, NULL); _text_passwd_update(); + + e_auth_fprint_begin(e_username_get()); + E_LIST_HANDLER_APPEND(edd->handlers, E_EVENT_AUTH_FPRINT_AVAILABLE, _lokker_cb_fprint_available, NULL); + E_LIST_HANDLER_APPEND(edd->handlers, E_EVENT_AUTH_FPRINT_STATUS, _lokker_cb_fprint_status, NULL); + return EINA_TRUE; } EINTERN void lokker_unlock(void) { + e_auth_fprint_end(); E_FREE_LIST(edd->elock_wnd_list, _lokker_popup_free); e_pointer_type_pop(e_comp->pointer, e_comp->pointer, "default"); e_pointer_type_pop(e_comp->pointer, NULL, NULL);