mirror of
https://gitlab.com/mishakmak/pam-fprint-grosshack.git
synced 2026-04-08 20:03:34 +02:00
pam: Stop authentication with PAM_AUTHINFO_UNAVAIL on name owner change
If fprintd disappears or is replaced, then we might be getting signals from another daemon/verifcation session. As such we must give up at that point. Related: #47
This commit is contained in:
@ -160,6 +160,9 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
char *dev;
|
||||||
|
bool has_multiple_devices;
|
||||||
|
|
||||||
unsigned max_tries;
|
unsigned max_tries;
|
||||||
char *result;
|
char *result;
|
||||||
bool timed_out;
|
bool timed_out;
|
||||||
@ -325,56 +328,49 @@ static int verify_started_cb (sd_bus_message *m,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
do_verify (pam_handle_t *pamh,
|
do_verify (sd_bus *bus,
|
||||||
sd_bus *bus,
|
verify_data *data)
|
||||||
const char *dev,
|
|
||||||
bool has_multiple_devices)
|
|
||||||
{
|
{
|
||||||
verify_data *data;
|
|
||||||
sd_bus_slot *verify_status_slot, *verify_finger_selected_slot;
|
sd_bus_slot *verify_status_slot, *verify_finger_selected_slot;
|
||||||
char *scan_type = NULL;
|
char *scan_type = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
data = calloc (1, sizeof(verify_data));
|
|
||||||
data->max_tries = max_tries;
|
|
||||||
data->pamh = pamh;
|
|
||||||
|
|
||||||
/* Get some properties for the device */
|
/* Get some properties for the device */
|
||||||
r = get_property_string (bus,
|
r = get_property_string (bus,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
dev,
|
data->dev,
|
||||||
"net.reactivated.Fprint.Device",
|
"net.reactivated.Fprint.Device",
|
||||||
"scan-type",
|
"scan-type",
|
||||||
NULL,
|
NULL,
|
||||||
&scan_type);
|
&scan_type);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
pam_syslog (data->pamh, LOG_ERR, "Failed to get scan-type for %s: %d", dev, r);
|
pam_syslog (data->pamh, LOG_ERR, "Failed to get scan-type for %s: %d", data->dev, r);
|
||||||
if (debug)
|
if (debug)
|
||||||
pam_syslog (data->pamh, LOG_DEBUG, "scan-type for %s: %s", dev, scan_type);
|
pam_syslog (data->pamh, LOG_DEBUG, "scan-type for %s: %s", data->dev, scan_type);
|
||||||
if (str_equal (scan_type, "swipe"))
|
if (str_equal (scan_type, "swipe"))
|
||||||
data->is_swipe = true;
|
data->is_swipe = true;
|
||||||
free (scan_type);
|
free (scan_type);
|
||||||
|
|
||||||
if (has_multiple_devices) {
|
if (data->has_multiple_devices) {
|
||||||
get_property_string (bus,
|
get_property_string (bus,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
dev,
|
data->dev,
|
||||||
"net.reactivated.Fprint.Device",
|
"net.reactivated.Fprint.Device",
|
||||||
"name",
|
"name",
|
||||||
NULL,
|
NULL,
|
||||||
&data->driver);
|
&data->driver);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
pam_syslog (data->pamh, LOG_ERR, "Failed to get driver name for %s: %d", dev, r);
|
pam_syslog (data->pamh, LOG_ERR, "Failed to get driver name for %s: %d", data->dev, r);
|
||||||
if (debug && r == 0)
|
if (debug && r == 0)
|
||||||
pam_syslog (data->pamh, LOG_DEBUG, "driver name for %s: %s", dev, data->driver);
|
pam_syslog (data->pamh, LOG_DEBUG, "driver name for %s: %s", data->dev, data->driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
verify_status_slot = NULL;
|
verify_status_slot = NULL;
|
||||||
sd_bus_match_signal (bus,
|
sd_bus_match_signal (bus,
|
||||||
&verify_status_slot,
|
&verify_status_slot,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
dev,
|
data->dev,
|
||||||
"net.reactivated.Fprint.Device",
|
"net.reactivated.Fprint.Device",
|
||||||
"VerifyStatus",
|
"VerifyStatus",
|
||||||
verify_result,
|
verify_result,
|
||||||
@ -384,7 +380,7 @@ do_verify (pam_handle_t *pamh,
|
|||||||
sd_bus_match_signal (bus,
|
sd_bus_match_signal (bus,
|
||||||
&verify_finger_selected_slot,
|
&verify_finger_selected_slot,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
dev,
|
data->dev,
|
||||||
"net.reactivated.Fprint.Device",
|
"net.reactivated.Fprint.Device",
|
||||||
"VerifyFingerSelected",
|
"VerifyFingerSelected",
|
||||||
verify_finger_selected,
|
verify_finger_selected,
|
||||||
@ -405,7 +401,7 @@ do_verify (pam_handle_t *pamh,
|
|||||||
r = sd_bus_call_method_async (bus,
|
r = sd_bus_call_method_async (bus,
|
||||||
NULL,
|
NULL,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
dev,
|
data->dev,
|
||||||
"net.reactivated.Fprint.Device",
|
"net.reactivated.Fprint.Device",
|
||||||
"VerifyStart",
|
"VerifyStart",
|
||||||
verify_started_cb,
|
verify_started_cb,
|
||||||
@ -415,7 +411,7 @@ do_verify (pam_handle_t *pamh,
|
|||||||
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (debug)
|
if (debug)
|
||||||
pam_syslog (pamh, LOG_DEBUG, "VerifyStart call failed: %d", r);
|
pam_syslog (data->pamh, LOG_DEBUG, "VerifyStart call failed: %d", r);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +433,8 @@ do_verify (pam_handle_t *pamh,
|
|||||||
break;
|
break;
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
if (debug) {
|
if (debug) {
|
||||||
pam_syslog(pamh, LOG_DEBUG, "Waiting for %"PRId64" seconds (%"PRId64" usecs)",
|
pam_syslog(data->pamh, LOG_DEBUG,
|
||||||
|
"Waiting for %"PRId64" seconds (%"PRId64" usecs)",
|
||||||
wait_time / USEC_PER_SEC,
|
wait_time / USEC_PER_SEC,
|
||||||
wait_time);
|
wait_time);
|
||||||
}
|
}
|
||||||
@ -461,7 +458,7 @@ do_verify (pam_handle_t *pamh,
|
|||||||
data->verify_started = false;
|
data->verify_started = false;
|
||||||
sd_bus_call_method (bus,
|
sd_bus_call_method (bus,
|
||||||
"net.reactivated.Fprint",
|
"net.reactivated.Fprint",
|
||||||
dev,
|
data->dev,
|
||||||
"net.reactivated.Fprint.Device",
|
"net.reactivated.Fprint.Device",
|
||||||
"VerifyStop",
|
"VerifyStop",
|
||||||
NULL,
|
NULL,
|
||||||
@ -501,11 +498,6 @@ do_verify (pam_handle_t *pamh,
|
|||||||
sd_bus_slot_unref (verify_status_slot);
|
sd_bus_slot_unref (verify_status_slot);
|
||||||
sd_bus_slot_unref (verify_finger_selected_slot);
|
sd_bus_slot_unref (verify_finger_selected_slot);
|
||||||
|
|
||||||
if (data->result)
|
|
||||||
free (data->result);
|
|
||||||
free (data->driver);
|
|
||||||
free (data);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,39 +601,88 @@ claim_device (pam_handle_t *pamh,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
name_owner_changed (sd_bus_message *m,
|
||||||
|
void *userdata,
|
||||||
|
sd_bus_error *ret_error)
|
||||||
|
{
|
||||||
|
verify_data *data = userdata;
|
||||||
|
const char *name = NULL;
|
||||||
|
const char *old_owner = NULL;
|
||||||
|
const char *new_owner = NULL;
|
||||||
|
|
||||||
|
if (sd_bus_message_read (m, "sss", &name, &old_owner, &new_owner) < 0) {
|
||||||
|
pam_syslog (data->pamh, LOG_ERR, "Failed to parse NameOwnerChanged signal: %d", errno);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp (name, "net.reactivated.Fprint") != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Name owner for fprintd changed, give up as we might start listening
|
||||||
|
* to events from a new name owner otherwise. */
|
||||||
|
data->verify_ret = PAM_AUTHINFO_UNAVAIL;
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
pam_syslog (data->pamh, LOG_ERR, "fprintd name owner changed during operation!\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_auth(pam_handle_t *pamh, const char *username)
|
static int do_auth(pam_handle_t *pamh, const char *username)
|
||||||
{
|
{
|
||||||
char *dev;
|
|
||||||
bool have_prints;
|
bool have_prints;
|
||||||
bool has_multiple_devices;
|
|
||||||
int ret = PAM_AUTHINFO_UNAVAIL;
|
int ret = PAM_AUTHINFO_UNAVAIL;
|
||||||
|
verify_data *data;
|
||||||
|
sd_bus_slot *name_owner_changed_slot;
|
||||||
sd_bus *bus = NULL;
|
sd_bus *bus = NULL;
|
||||||
|
|
||||||
|
data = calloc (1, sizeof(verify_data));
|
||||||
|
data->max_tries = max_tries;
|
||||||
|
data->pamh = pamh;
|
||||||
|
|
||||||
if (sd_bus_open_system (&bus) < 0) {
|
if (sd_bus_open_system (&bus) < 0) {
|
||||||
pam_syslog (pamh, LOG_ERR, "Error with getting the bus: %d", errno);
|
pam_syslog (pamh, LOG_ERR, "Error with getting the bus: %d", errno);
|
||||||
return PAM_AUTHINFO_UNAVAIL;
|
return PAM_AUTHINFO_UNAVAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = open_device (pamh, bus, &has_multiple_devices);
|
name_owner_changed_slot = NULL;
|
||||||
if (dev == NULL) {
|
sd_bus_match_signal (bus,
|
||||||
|
&name_owner_changed_slot,
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"/org/freedesktop/DBus",
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"NameOwnerChanged",
|
||||||
|
name_owner_changed,
|
||||||
|
data);
|
||||||
|
|
||||||
|
data->dev = open_device (pamh, bus, &data->has_multiple_devices);
|
||||||
|
if (data->dev == NULL) {
|
||||||
sd_bus_unref (bus);
|
sd_bus_unref (bus);
|
||||||
return PAM_AUTHINFO_UNAVAIL;
|
return PAM_AUTHINFO_UNAVAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
have_prints = user_has_prints (pamh, bus, dev, username);
|
have_prints = user_has_prints (pamh, bus, data->dev, username);
|
||||||
if (debug)
|
if (debug)
|
||||||
pam_syslog (pamh, LOG_DEBUG, "prints registered: %s\n", have_prints ? "yes" : "no");
|
pam_syslog (pamh, LOG_DEBUG, "prints registered: %s\n", have_prints ? "yes" : "no");
|
||||||
|
|
||||||
if (!have_prints)
|
if (!have_prints)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (claim_device (pamh, bus, dev, username)) {
|
if (claim_device (pamh, bus, data->dev, username)) {
|
||||||
ret = do_verify (pamh, bus, dev, has_multiple_devices);
|
ret = do_verify (bus, data);
|
||||||
release_device (pamh, bus, dev);
|
release_device (pamh, bus, data->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free (dev);
|
sd_bus_slot_unref (name_owner_changed_slot);
|
||||||
|
|
||||||
|
if (data->result)
|
||||||
|
free (data->result);
|
||||||
|
free (data->driver);
|
||||||
|
free (data->dev);
|
||||||
|
free (data);
|
||||||
|
|
||||||
sd_bus_unref (bus);
|
sd_bus_unref (bus);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user