|
Packit Service |
f1aff6 |
/*
|
|
Packit Service |
f1aff6 |
* pam_fprint: PAM module for fingerprint authentication through fprintd
|
|
Packit Service |
f1aff6 |
* Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
|
|
Packit Service |
8ebd8e |
* Copyright (C) 2008-2014, 2017-2020 Bastien Nocera <hadess@hadess.net>
|
|
Packit Service |
f1aff6 |
*
|
|
Packit Service |
f1aff6 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
f1aff6 |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
f1aff6 |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit Service |
f1aff6 |
* (at your option) any later version.
|
|
Packit Service |
f1aff6 |
*
|
|
Packit Service |
f1aff6 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
f1aff6 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
f1aff6 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
f1aff6 |
* GNU General Public License for more details.
|
|
Packit Service |
f1aff6 |
*
|
|
Packit Service |
f1aff6 |
* You should have received a copy of the GNU General Public License along
|
|
Packit Service |
f1aff6 |
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit Service |
f1aff6 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit Service |
f1aff6 |
*/
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
f1aff6 |
#include <config.h>
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
#define _GNU_SOURCE
|
|
Packit Service |
f1aff6 |
#include <stdio.h>
|
|
Packit Service |
f1aff6 |
#include <stdlib.h>
|
|
Packit Service |
8ebd8e |
#include <stdint.h>
|
|
Packit Service |
f1aff6 |
#include <unistd.h>
|
|
Packit Service |
f1aff6 |
#include <sys/types.h>
|
|
Packit Service |
f1aff6 |
#include <string.h>
|
|
Packit Service |
f1aff6 |
#include <syslog.h>
|
|
Packit Service |
8ebd8e |
#include <errno.h>
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
#include <libintl.h>
|
|
Packit Service |
8ebd8e |
#include <systemd/sd-bus.h>
|
|
Packit Service |
8ebd8e |
#include <systemd/sd-login.h>
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
f1aff6 |
#define PAM_SM_AUTH
|
|
Packit Service |
f1aff6 |
#include <security/pam_modules.h>
|
|
Packit Service |
8ebd8e |
#include <security/pam_ext.h>
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
#define _(s) ((char *) dgettext (GETTEXT_PACKAGE, s))
|
|
Packit Service |
8ebd8e |
#define TR(s) dgettext (GETTEXT_PACKAGE, s)
|
|
Packit Service |
8ebd8e |
#define N_(s) (s)
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
f1aff6 |
#include "fingerprint-strings.h"
|
|
Packit Service |
8ebd8e |
#include "pam_fprintd_autoptrs.h"
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
f1aff6 |
#define DEFAULT_MAX_TRIES 3
|
|
Packit Service |
f1aff6 |
#define DEFAULT_TIMEOUT 30
|
|
Packit Service |
8ebd8e |
#define MIN_TIMEOUT 10
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
#define DEBUG_MATCH "debug="
|
|
Packit Service |
f1aff6 |
#define MAX_TRIES_MATCH "max-tries="
|
|
Packit Service |
f1aff6 |
#define TIMEOUT_MATCH "timeout="
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static bool debug = false;
|
|
Packit Service |
8ebd8e |
static unsigned max_tries = DEFAULT_MAX_TRIES;
|
|
Packit Service |
8ebd8e |
static unsigned timeout = DEFAULT_TIMEOUT;
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
#define USEC_PER_SEC ((uint64_t) 1000000ULL)
|
|
Packit Service |
8ebd8e |
#define NSEC_PER_USEC ((uint64_t) 1000ULL)
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static uint64_t
|
|
Packit Service |
8ebd8e |
now (void)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
struct timespec ts;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
clock_gettime (CLOCK_MONOTONIC, &ts);
|
|
Packit Service |
8ebd8e |
return (uint64_t) ts.tv_sec * USEC_PER_SEC + (uint64_t) ts.tv_nsec / NSEC_PER_USEC;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static bool
|
|
Packit Service |
8ebd8e |
str_has_prefix (const char *s, const char *prefix)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
if (s == NULL || prefix == NULL)
|
|
Packit Service |
8ebd8e |
return false;
|
|
Packit Service |
8ebd8e |
return strncmp (s, prefix, strlen (prefix)) == 0;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static bool
|
|
Packit Service |
8ebd8e |
send_msg (pam_handle_t *pamh, const char *msg, int style)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
const struct pam_message mymsg = {
|
|
Packit Service |
8ebd8e |
.msg_style = style,
|
|
Packit Service |
8ebd8e |
.msg = msg,
|
|
Packit Service |
8ebd8e |
};
|
|
Packit Service |
8ebd8e |
const struct pam_message *msgp = &mymsg;
|
|
Packit Service |
8ebd8e |
const struct pam_conv *pc;
|
|
Packit Service |
8ebd8e |
struct pam_response *resp;
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
if (pam_get_item (pamh, PAM_CONV, (const void **) &pc) != PAM_SUCCESS)
|
|
Packit Service |
8ebd8e |
return false;
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
if (!pc || !pc->conv)
|
|
Packit Service |
8ebd8e |
return false;
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
return pc->conv (1, &msgp, &resp, pc->appdata_ptr) == PAM_SUCCESS;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static bool
|
|
Packit Service |
8ebd8e |
send_info_msg (pam_handle_t *pamh, const char *msg)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
return send_msg (pamh, msg, PAM_TEXT_INFO);
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static bool
|
|
Packit Service |
8ebd8e |
send_err_msg (pam_handle_t *pamh, const char *msg)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
return send_msg (pamh, msg, PAM_ERROR_MSG);
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static char *
|
|
Packit Service |
8ebd8e |
open_device (pam_handle_t *pamh,
|
|
Packit Service |
8ebd8e |
sd_bus *bus,
|
|
Packit Service |
8ebd8e |
bool *has_multiple_devices)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
|
|
Packit Service |
8ebd8e |
pf_autoptr (sd_bus_message) m = NULL;
|
|
Packit Service |
8ebd8e |
size_t num_devices;
|
|
Packit Service |
8ebd8e |
const char *path = NULL;
|
|
Packit Service |
8ebd8e |
const char *s;
|
|
Packit Service |
8ebd8e |
int r;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
*has_multiple_devices = false;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (sd_bus_call_method (bus,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint",
|
|
Packit Service |
8ebd8e |
"/net/reactivated/Fprint/Manager",
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint.Manager",
|
|
Packit Service |
8ebd8e |
"GetDevices",
|
|
Packit Service |
8ebd8e |
&error,
|
|
Packit Service |
8ebd8e |
&m,
|
|
Packit Service |
8ebd8e |
NULL) < 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_ERR, "GetDevices failed: %s", error.message);
|
|
Packit Service |
8ebd8e |
return NULL;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
r = sd_bus_message_enter_container (m, 'a', "o");
|
|
Packit Service |
8ebd8e |
if (r < 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_ERR, "Failed to parse answer from GetDevices(): %d", r);
|
|
Packit Service |
8ebd8e |
return NULL;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (sd_bus_message_read_basic (m, 'o', &path) < 0)
|
|
Packit Service |
8ebd8e |
return NULL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
num_devices = 1;
|
|
Packit Service |
8ebd8e |
while ((r = sd_bus_message_read_basic (m, 'o', &s)) > 0)
|
|
Packit Service |
8ebd8e |
num_devices++;
|
|
Packit Service |
8ebd8e |
*has_multiple_devices = (num_devices > 1);
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "Using device %s (out of %ld devices)", path, num_devices);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
sd_bus_message_exit_container (m);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
return path ? strdup (path) : NULL;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
typedef struct
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
char *dev;
|
|
Packit Service |
8ebd8e |
bool has_multiple_devices;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
unsigned max_tries;
|
|
Packit Service |
8ebd8e |
char *result;
|
|
Packit Service |
8ebd8e |
bool timed_out;
|
|
Packit Service |
8ebd8e |
bool is_swipe;
|
|
Packit Service |
8ebd8e |
bool verify_started;
|
|
Packit Service |
8ebd8e |
int verify_ret;
|
|
Packit Service |
8ebd8e |
pam_handle_t *pamh;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
char *driver;
|
|
Packit Service |
8ebd8e |
} verify_data;
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static void
|
|
Packit Service |
8ebd8e |
verify_data_free (verify_data *data)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
free (data->result);
|
|
Packit Service |
8ebd8e |
free (data->driver);
|
|
Packit Service |
8ebd8e |
free (data->dev);
|
|
Packit Service |
8ebd8e |
free (data);
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
PF_DEFINE_AUTOPTR_CLEANUP_FUNC (verify_data, verify_data_free)
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static int
|
|
Packit Service |
8ebd8e |
verify_result (sd_bus_message *m,
|
|
Packit Service |
8ebd8e |
void *userdata,
|
|
Packit Service |
8ebd8e |
sd_bus_error *ret_error)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
verify_data *data = userdata;
|
|
Packit Service |
8ebd8e |
const char *msg;
|
|
Packit Service |
8ebd8e |
const char *result = NULL;
|
|
Packit Service |
8ebd8e |
/* see https://github.com/systemd/systemd/issues/14643 */
|
|
Packit Service |
8ebd8e |
uint64_t done = false;
|
|
Packit Service |
8ebd8e |
int r;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (!sd_bus_message_is_signal (m, "net.reactivated.Fprint.Device", "VerifyStatus"))
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_ERR, "Not the signal we expected (iface: %s, member: %s)",
|
|
Packit Service |
8ebd8e |
sd_bus_message_get_interface (m),
|
|
Packit Service |
8ebd8e |
sd_bus_message_get_member (m));
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if ((r = sd_bus_message_read (m, "sb", &result, &done)) < 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_ERR, "Failed to parse VerifyResult signal: %d", r);
|
|
Packit Service |
8ebd8e |
data->verify_ret = PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (!data->verify_started)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_ERR, "Unexpected VerifyResult '%s', %" PRIu64 " signal", result, done);
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_DEBUG, "Verify result: %s (done: %d)", result, done ? 1 : 0);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (data->result)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
free (data->result);
|
|
Packit Service |
8ebd8e |
data->result = NULL;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (done && result)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
data->result = strdup (result);
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
msg = verify_result_str_to_msg (result, data->is_swipe);
|
|
Packit Service |
8ebd8e |
if (!msg)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
data->result = strdup ("Protocol error with fprintd!");
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
send_err_msg (data->pamh, msg);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static int
|
|
Packit Service |
8ebd8e |
verify_finger_selected (sd_bus_message *m,
|
|
Packit Service |
8ebd8e |
void *userdata,
|
|
Packit Service |
8ebd8e |
sd_bus_error *ret_error)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
verify_data *data = userdata;
|
|
Packit Service |
8ebd8e |
const char *finger_name = NULL;
|
|
Packit Service |
8ebd8e |
pf_autofree char *msg = NULL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (sd_bus_message_read_basic (m, 's', &finger_name) < 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_ERR, "Failed to parse VerifyFingerSelected signal: %d", errno);
|
|
Packit Service |
8ebd8e |
data->verify_ret = PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (!data->verify_started)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_ERR, "Unexpected VerifyFingerSelected %s signal", finger_name);
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
msg = finger_str_to_msg (finger_name, data->driver, data->is_swipe);
|
|
Packit Service |
8ebd8e |
if (!msg)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
data->result = strdup ("Protocol error with fprintd!");
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_DEBUG, "verify_finger_selected %s", msg);
|
|
Packit Service |
8ebd8e |
send_info_msg (data->pamh, msg);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
/* See https://github.com/systemd/systemd/issues/14636 */
|
|
Packit Service |
8ebd8e |
static int
|
|
Packit Service |
8ebd8e |
get_property_string (sd_bus *bus,
|
|
Packit Service |
8ebd8e |
const char *destination,
|
|
Packit Service |
8ebd8e |
const char *path,
|
|
Packit Service |
8ebd8e |
const char *interface,
|
|
Packit Service |
8ebd8e |
const char *member,
|
|
Packit Service |
8ebd8e |
sd_bus_error *error,
|
|
Packit Service |
8ebd8e |
char **ret)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
pf_autoptr (sd_bus_message) reply = NULL;
|
|
Packit Service |
8ebd8e |
const char *s;
|
|
Packit Service |
8ebd8e |
char *n;
|
|
Packit Service |
8ebd8e |
int r;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
r = sd_bus_call_method (bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", interface, member);
|
|
Packit Service |
8ebd8e |
if (r < 0)
|
|
Packit Service |
8ebd8e |
return r;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
r = sd_bus_message_enter_container (reply, 'v', "s");
|
|
Packit Service |
8ebd8e |
if (r < 0)
|
|
Packit Service |
8ebd8e |
return sd_bus_error_set_errno (error, r);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
r = sd_bus_message_read_basic (reply, 's', &s);
|
|
Packit Service |
8ebd8e |
if (r < 0)
|
|
Packit Service |
8ebd8e |
return sd_bus_error_set_errno (error, r);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
n = strdup (s);
|
|
Packit Service |
8ebd8e |
if (!n)
|
|
Packit Service |
8ebd8e |
return sd_bus_error_set_errno (error, -ENOMEM);
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
*ret = n;
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
static int
|
|
Packit Service |
8ebd8e |
verify_started_cb (sd_bus_message *m,
|
|
Packit Service |
8ebd8e |
void *userdata,
|
|
Packit Service |
8ebd8e |
sd_bus_error *ret_error)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
const sd_bus_error *error = sd_bus_message_get_error (m);
|
|
Packit Service |
8ebd8e |
verify_data *data = userdata;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (error)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
if (sd_bus_error_has_name (error, "net.reactivated.Fprint.Error.NoEnrolledPrints"))
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_DEBUG, "No prints enrolled");
|
|
Packit Service |
8ebd8e |
data->verify_ret = PAM_USER_UNKNOWN;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
data->verify_ret = PAM_AUTH_ERR;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_DEBUG, "VerifyStart failed: %s", error->message);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
return 1;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_DEBUG, "VerifyStart completed successfully");
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
data->verify_started = true;
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
return 1;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static int
|
|
Packit Service |
8ebd8e |
do_verify (sd_bus *bus,
|
|
Packit Service |
8ebd8e |
verify_data *data)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
pf_autoptr (sd_bus_slot) verify_status_slot = NULL;
|
|
Packit Service |
8ebd8e |
pf_autoptr (sd_bus_slot) verify_finger_selected_slot = NULL;
|
|
Packit Service |
8ebd8e |
pf_autofree char *scan_type = NULL;
|
|
Packit Service |
8ebd8e |
int r;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
/* Get some properties for the device */
|
|
Packit Service |
8ebd8e |
r = get_property_string (bus,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint",
|
|
Packit Service |
8ebd8e |
data->dev,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint.Device",
|
|
Packit Service |
8ebd8e |
"scan-type",
|
|
Packit Service |
8ebd8e |
NULL,
|
|
Packit Service |
8ebd8e |
&scan_type);
|
|
Packit Service |
8ebd8e |
if (r < 0)
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_ERR, "Failed to get scan-type for %s: %d", data->dev, r);
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_DEBUG, "scan-type for %s: %s", data->dev, scan_type);
|
|
Packit Service |
8ebd8e |
if (str_equal (scan_type, "swipe"))
|
|
Packit Service |
8ebd8e |
data->is_swipe = true;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (data->has_multiple_devices)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
get_property_string (bus,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint",
|
|
Packit Service |
8ebd8e |
data->dev,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint.Device",
|
|
Packit Service |
8ebd8e |
"name",
|
|
Packit Service |
8ebd8e |
NULL,
|
|
Packit Service |
8ebd8e |
&data->driver);
|
|
Packit Service |
8ebd8e |
if (r < 0)
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_ERR, "Failed to get driver name for %s: %d", data->dev, r);
|
|
Packit Service |
8ebd8e |
if (debug && r == 0)
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_DEBUG, "driver name for %s: %s", data->dev, data->driver);
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
sd_bus_match_signal (bus,
|
|
Packit Service |
8ebd8e |
&verify_status_slot,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint",
|
|
Packit Service |
8ebd8e |
data->dev,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint.Device",
|
|
Packit Service |
8ebd8e |
"VerifyStatus",
|
|
Packit Service |
8ebd8e |
verify_result,
|
|
Packit Service |
8ebd8e |
data);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
sd_bus_match_signal (bus,
|
|
Packit Service |
8ebd8e |
&verify_finger_selected_slot,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint",
|
|
Packit Service |
8ebd8e |
data->dev,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint.Device",
|
|
Packit Service |
8ebd8e |
"VerifyFingerSelected",
|
|
Packit Service |
8ebd8e |
verify_finger_selected,
|
|
Packit Service |
8ebd8e |
data);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
while (data->max_tries > 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
uint64_t verification_end = now () + (timeout * USEC_PER_SEC);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
data->timed_out = false;
|
|
Packit Service |
8ebd8e |
data->verify_started = false;
|
|
Packit Service |
8ebd8e |
data->verify_ret = PAM_INCOMPLETE;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
free (data->result);
|
|
Packit Service |
8ebd8e |
data->result = NULL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_DEBUG, "About to call VerifyStart");
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
r = sd_bus_call_method_async (bus,
|
|
Packit Service |
8ebd8e |
NULL,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint",
|
|
Packit Service |
8ebd8e |
data->dev,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint.Device",
|
|
Packit Service |
8ebd8e |
"VerifyStart",
|
|
Packit Service |
8ebd8e |
verify_started_cb,
|
|
Packit Service |
8ebd8e |
data,
|
|
Packit Service |
8ebd8e |
"s",
|
|
Packit Service |
8ebd8e |
"any");
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (r < 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_DEBUG, "VerifyStart call failed: %d", r);
|
|
Packit Service |
8ebd8e |
break;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
for (;;)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
int64_t wait_time;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
wait_time = verification_end - now ();
|
|
Packit Service |
8ebd8e |
if (wait_time <= 0)
|
|
Packit Service |
8ebd8e |
break;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
r = sd_bus_process (bus, NULL);
|
|
Packit Service |
8ebd8e |
if (r < 0)
|
|
Packit Service |
8ebd8e |
break;
|
|
Packit Service |
8ebd8e |
if (data->verify_ret != PAM_INCOMPLETE)
|
|
Packit Service |
8ebd8e |
break;
|
|
Packit Service |
8ebd8e |
if (!data->verify_started)
|
|
Packit Service |
8ebd8e |
continue;
|
|
Packit Service |
8ebd8e |
if (data->result != NULL)
|
|
Packit Service |
8ebd8e |
break;
|
|
Packit Service |
8ebd8e |
if (r == 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_DEBUG,
|
|
Packit Service |
8ebd8e |
"Waiting for %" PRId64 " seconds (%" PRId64 " usecs)",
|
|
Packit Service |
8ebd8e |
wait_time / USEC_PER_SEC,
|
|
Packit Service |
8ebd8e |
wait_time);
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
if (sd_bus_wait (bus, wait_time) < 0)
|
|
Packit Service |
8ebd8e |
break;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (data->verify_ret != PAM_INCOMPLETE)
|
|
Packit Service |
8ebd8e |
return data->verify_ret;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (now () >= verification_end)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
data->timed_out = true;
|
|
Packit Service |
8ebd8e |
send_info_msg (data->pamh, _("Verification timed out"));
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
/* Ignore errors from VerifyStop */
|
|
Packit Service |
8ebd8e |
data->verify_started = false;
|
|
Packit Service |
8ebd8e |
sd_bus_call_method (bus,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint",
|
|
Packit Service |
8ebd8e |
data->dev,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint.Device",
|
|
Packit Service |
8ebd8e |
"VerifyStop",
|
|
Packit Service |
8ebd8e |
NULL,
|
|
Packit Service |
8ebd8e |
NULL,
|
|
Packit Service |
8ebd8e |
NULL,
|
|
Packit Service |
8ebd8e |
NULL);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (data->timed_out)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
return PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
if (str_equal (data->result, "verify-no-match"))
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
send_err_msg (data->pamh, "Failed to match fingerprint");
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else if (str_equal (data->result, "verify-match"))
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
return PAM_SUCCESS;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else if (str_equal (data->result, "verify-unknown-error"))
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
return PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else if (str_equal (data->result, "verify-disconnected"))
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
return PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
send_err_msg (data->pamh, _("An unknown error occurred"));
|
|
Packit Service |
8ebd8e |
return PAM_AUTH_ERR;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
data->max_tries--;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (data->max_tries == 0)
|
|
Packit Service |
8ebd8e |
return PAM_MAXTRIES;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
return PAM_AUTH_ERR;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static bool
|
|
Packit Service |
8ebd8e |
user_has_prints (pam_handle_t *pamh,
|
|
Packit Service |
8ebd8e |
sd_bus *bus,
|
|
Packit Service |
8ebd8e |
const char *dev,
|
|
Packit Service |
8ebd8e |
const char *username)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
|
|
Packit Service |
8ebd8e |
pf_autoptr (sd_bus_message) m = NULL;
|
|
Packit Service |
8ebd8e |
size_t num_fingers = 0;
|
|
Packit Service |
8ebd8e |
const char *s;
|
|
Packit Service |
8ebd8e |
int r;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
r = sd_bus_call_method (bus,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint",
|
|
Packit Service |
8ebd8e |
dev,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint.Device",
|
|
Packit Service |
8ebd8e |
"ListEnrolledFingers",
|
|
Packit Service |
8ebd8e |
&error,
|
|
Packit Service |
8ebd8e |
&m,
|
|
Packit Service |
8ebd8e |
"s",
|
|
Packit Service |
8ebd8e |
username);
|
|
Packit Service |
8ebd8e |
if (r < 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
/* If ListEnrolledFingers fails then verification should
|
|
Packit Service |
8ebd8e |
* also fail (both use the same underlying call), so we
|
|
Packit Service |
8ebd8e |
* report false here and bail out early. */
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "ListEnrolledFingers failed for %s: %s",
|
|
Packit Service |
8ebd8e |
username, error.message);
|
|
Packit Service |
8ebd8e |
return false;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
r = sd_bus_message_enter_container (m, 'a', "s");
|
|
Packit Service |
8ebd8e |
if (r < 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_ERR, "Failed to parse answer from ListEnrolledFingers(): %d", r);
|
|
Packit Service |
8ebd8e |
return false;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
while ((r = sd_bus_message_read_basic (m, 's', &s)) > 0)
|
|
Packit Service |
8ebd8e |
num_fingers++;
|
|
Packit Service |
8ebd8e |
sd_bus_message_exit_container (m);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
return num_fingers > 0;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static void
|
|
Packit Service |
8ebd8e |
release_device (pam_handle_t *pamh,
|
|
Packit Service |
8ebd8e |
sd_bus *bus,
|
|
Packit Service |
8ebd8e |
const char *dev)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (sd_bus_call_method (bus,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint",
|
|
Packit Service |
8ebd8e |
dev,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint.Device",
|
|
Packit Service |
8ebd8e |
"Release",
|
|
Packit Service |
8ebd8e |
&error,
|
|
Packit Service |
8ebd8e |
NULL,
|
|
Packit Service |
8ebd8e |
NULL,
|
|
Packit Service |
8ebd8e |
NULL) < 0)
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_ERR, "ReleaseDevice failed: %s", error.message);
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static bool
|
|
Packit Service |
8ebd8e |
claim_device (pam_handle_t *pamh,
|
|
Packit Service |
8ebd8e |
sd_bus *bus,
|
|
Packit Service |
8ebd8e |
const char *dev,
|
|
Packit Service |
8ebd8e |
const char *username)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
pf_auto (sd_bus_error) error = SD_BUS_ERROR_NULL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (sd_bus_call_method (bus,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint",
|
|
Packit Service |
8ebd8e |
dev,
|
|
Packit Service |
8ebd8e |
"net.reactivated.Fprint.Device",
|
|
Packit Service |
8ebd8e |
"Claim",
|
|
Packit Service |
8ebd8e |
&error,
|
|
Packit Service |
8ebd8e |
NULL,
|
|
Packit Service |
8ebd8e |
"s",
|
|
Packit Service |
8ebd8e |
username) < 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "failed to claim device %s", error.message);
|
|
Packit Service |
8ebd8e |
return false;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
return true;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
static int
|
|
Packit Service |
8ebd8e |
name_owner_changed (sd_bus_message *m,
|
|
Packit Service |
8ebd8e |
void *userdata,
|
|
Packit Service |
8ebd8e |
sd_bus_error *ret_error)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
verify_data *data = userdata;
|
|
Packit Service |
8ebd8e |
const char *name = NULL;
|
|
Packit Service |
8ebd8e |
const char *old_owner = NULL;
|
|
Packit Service |
8ebd8e |
const char *new_owner = NULL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (sd_bus_message_read (m, "sss", &name, &old_owner, &new_owner) < 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_ERR, "Failed to parse NameOwnerChanged signal: %d", errno);
|
|
Packit Service |
8ebd8e |
data->verify_ret = PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
if (strcmp (name, "net.reactivated.Fprint") != 0)
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
/* Name owner for fprintd changed, give up as we might start listening
|
|
Packit Service |
8ebd8e |
* to events from a new name owner otherwise. */
|
|
Packit Service |
8ebd8e |
data->verify_ret = PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
pam_syslog (data->pamh, LOG_WARNING, "fprintd name owner changed during operation!");
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
return 0;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static int
|
|
Packit Service |
8ebd8e |
do_auth (pam_handle_t *pamh, const char *username)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
bool have_prints;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
pf_autoptr (verify_data) data = NULL;
|
|
Packit Service |
8ebd8e |
pf_autoptr (sd_bus) bus = NULL;
|
|
Packit Service |
8ebd8e |
pf_autoptr (sd_bus_slot) name_owner_changed_slot = NULL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
data = calloc (1, sizeof (verify_data));
|
|
Packit Service |
8ebd8e |
data->max_tries = max_tries;
|
|
Packit Service |
8ebd8e |
data->pamh = pamh;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (sd_bus_open_system (&bus) < 0)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_ERR, "Error with getting the bus: %d", errno);
|
|
Packit Service |
8ebd8e |
return PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
data->dev = open_device (pamh, bus, &data->has_multiple_devices);
|
|
Packit Service |
8ebd8e |
if (data->dev == NULL)
|
|
Packit Service |
8ebd8e |
return PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
have_prints = user_has_prints (pamh, bus, data->dev, username);
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "prints registered: %s\n", have_prints ? "yes" : "no");
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (!have_prints)
|
|
Packit Service |
8ebd8e |
return PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
/* Only connect to NameOwnerChanged when needed. In case of automatic startup
|
|
Packit Service |
8ebd8e |
* we rely on the fact that we never see those signals.
|
|
Packit Service |
8ebd8e |
*/
|
|
Packit Service |
8ebd8e |
name_owner_changed_slot = NULL;
|
|
Packit Service |
8ebd8e |
sd_bus_match_signal (bus,
|
|
Packit Service |
8ebd8e |
&name_owner_changed_slot,
|
|
Packit Service |
8ebd8e |
"org.freedesktop.DBus",
|
|
Packit Service |
8ebd8e |
"/org/freedesktop/DBus",
|
|
Packit Service |
8ebd8e |
"org.freedesktop.DBus",
|
|
Packit Service |
8ebd8e |
"NameOwnerChanged",
|
|
Packit Service |
8ebd8e |
name_owner_changed,
|
|
Packit Service |
8ebd8e |
data);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (claim_device (pamh, bus, data->dev, username))
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
int ret = do_verify (bus, data);
|
|
Packit Service |
8ebd8e |
release_device (pamh, bus, data->dev);
|
|
Packit Service |
8ebd8e |
return ret;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
return PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
static bool
|
|
Packit Service |
8ebd8e |
is_remote (pam_handle_t *pamh)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
const char *rhost = NULL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
pam_get_item (pamh, PAM_RHOST, (const void **) (const void *) &rhost);
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
/* NULL or empty rhost if the host information is not available or set.
|
|
Packit Service |
8ebd8e |
* "localhost" if the host is local.
|
|
Packit Service |
8ebd8e |
* We want to not run for known remote hosts */
|
|
Packit Service |
8ebd8e |
if (rhost != NULL &&
|
|
Packit Service |
8ebd8e |
*rhost != '\0' &&
|
|
Packit Service |
8ebd8e |
strcmp (rhost, "localhost") != 0)
|
|
Packit Service |
8ebd8e |
return true;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (sd_session_is_remote (NULL) > 0)
|
|
Packit Service |
8ebd8e |
return true;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
return false;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
PAM_EXTERN int
|
|
Packit Service |
8ebd8e |
pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc,
|
|
Packit Service |
8ebd8e |
const char **argv)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
const char *username;
|
|
Packit Service |
8ebd8e |
int i;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
|
|
Packit Service |
8ebd8e |
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (is_remote (pamh))
|
|
Packit Service |
8ebd8e |
return PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
if (pam_get_user (pamh, &username, NULL) != PAM_SUCCESS)
|
|
Packit Service |
8ebd8e |
return PAM_AUTHINFO_UNAVAIL;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
for (i = 0; i < argc; i++)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
if (argv[i] != NULL)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
if (str_equal (argv[i], "debug"))
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "debug on");
|
|
Packit Service |
8ebd8e |
debug = true;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else if (str_has_prefix (argv[i], DEBUG_MATCH))
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "debug on");
|
|
Packit Service |
8ebd8e |
const char *value;
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
value = argv[i] + strlen (DEBUG_MATCH);
|
|
Packit Service |
8ebd8e |
if (str_equal (value, "on") ||
|
|
Packit Service |
8ebd8e |
str_equal (value, "true") ||
|
|
Packit Service |
8ebd8e |
str_equal (value, "1"))
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "debug on");
|
|
Packit Service |
8ebd8e |
debug = true;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else if (str_equal (value, "off") ||
|
|
Packit Service |
8ebd8e |
str_equal (value, "false") ||
|
|
Packit Service |
8ebd8e |
str_equal (value, "0"))
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
debug = false;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "invalid debug value '%s', disabling", value);
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else if (str_has_prefix (argv[i], MAX_TRIES_MATCH) && strlen (argv[i]) == strlen (MAX_TRIES_MATCH) + 1)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
max_tries = atoi (argv[i] + strlen (MAX_TRIES_MATCH));
|
|
Packit Service |
8ebd8e |
if (max_tries < 1)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "invalid max tries '%s', using %d",
|
|
Packit Service |
8ebd8e |
argv[i] + strlen (MAX_TRIES_MATCH), DEFAULT_MAX_TRIES);
|
|
Packit Service |
8ebd8e |
max_tries = DEFAULT_MAX_TRIES;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "max_tries specified as: %d", max_tries);
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else if (str_has_prefix (argv[i], TIMEOUT_MATCH) && strlen (argv[i]) <= strlen (TIMEOUT_MATCH) + 2)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
timeout = atoi (argv[i] + strlen (TIMEOUT_MATCH));
|
|
Packit Service |
8ebd8e |
if (timeout < MIN_TIMEOUT)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
if (debug)
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "timeout %d secs too low, using %d",
|
|
Packit Service |
8ebd8e |
timeout, MIN_TIMEOUT);
|
|
Packit Service |
8ebd8e |
timeout = MIN_TIMEOUT;
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
else if (debug)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
pam_syslog (pamh, LOG_DEBUG, "timeout specified as: %d secs", timeout);
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
}
|
|
Packit Service |
8ebd8e |
|
|
Packit Service |
8ebd8e |
return do_auth (pamh, username);
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
PAM_EXTERN int
|
|
Packit Service |
8ebd8e |
pam_sm_setcred (pam_handle_t *pamh, int flags, int argc,
|
|
Packit Service |
8ebd8e |
const char **argv)
|
|
Packit Service |
f1aff6 |
{
|
|
Packit Service |
8ebd8e |
return PAM_SUCCESS;
|
|
Packit Service |
f1aff6 |
}
|
|
Packit Service |
f1aff6 |
|
|
Packit Service |
8ebd8e |
PAM_EXTERN int
|
|
Packit Service |
8ebd8e |
pam_sm_chauthtok (pam_handle_t *pamh, int flags, int argc,
|
|
Packit Service |
8ebd8e |
const char **argv)
|
|
Packit Service |
8ebd8e |
{
|
|
Packit Service |
8ebd8e |
return PAM_SUCCESS;
|
|
Packit Service |
8ebd8e |
}
|