test
reionwong 4 years ago
parent c27ce2ebcf
commit f4a380bb45

@ -122,6 +122,7 @@ static struct pam_conv PAM_conversation = {
#ifdef PAM_FAIL_DELAY
static void fail_delay(int retval ATTR_UNUSED, unsigned usec_delay ATTR_UNUSED, void *appdata_ptr ATTR_UNUSED)
{
}
#endif
@ -134,70 +135,94 @@ AuthReturn Authenticate(const char *method, const char *user, char *(*conv)(Conv
char pservb[64];
int pam_error;
openlog("kcheckpass", LOG_PID, LOG_AUTH);
int ret;
PAM_data.conv = conv;
if (strcmp(method, "classic")) {
sprintf(pservb, "%.31s-%.31s", KSCREENSAVER_PAM_SERVICE, method);
pam_service = pservb;
} else {
/* PAM_data.classic = 1; */
pam_service = KSCREENSAVER_PAM_SERVICE;
}
pam_error = pam_start(pam_service, user, &PAM_conversation, &pamh);
if (pam_error != PAM_SUCCESS) {
return AuthError;
}
ret = pam_start("cutefish", user, &PAM_conversation, &pamh);
tty = ttyname(0);
if (!tty) {
tty = getenv("DISPLAY");
}
message("%d hello", ret);
pam_error = pam_set_item(pamh, PAM_TTY, tty);
if (pam_error != PAM_SUCCESS) {
pam_end(pamh, pam_error);
if (ret != PAM_SUCCESS) {
message("PAM started failed\n");
return AuthError;
}
#ifdef PAM_FAIL_DELAY
pam_set_item(pamh, PAM_FAIL_DELAY, (void *)fail_delay);
#endif
pam_error = pam_authenticate(pamh, 0);
if (pam_error != PAM_SUCCESS) {
if (PAM_data.abort) {
PAM_data.abort = 0;
pam_end(pamh, pam_error);
return AuthAbort;
}
pam_end(pamh, pam_error);
switch (pam_error) {
case PAM_USER_UNKNOWN:
case PAM_AUTH_ERR:
case PAM_MAXTRIES: /* should handle this better ... */
case PAM_AUTHINFO_UNAVAIL: /* returned for unknown users ... bogus */
return AuthBad;
default:
return AuthError;
}
int auth_status = pam_authenticate(pamh, 0);
if (auth_status != PAM_SUCCESS) {
message("Auth Status: %s\n", pam_strerror(pamh, auth_status));
return AuthError;
}
/* just in case some module is stupid enough to ignore a preset PAM_USER */
pam_error = pam_get_item(pamh, PAM_USER, &pam_item);
if (pam_error != PAM_SUCCESS) {
pam_end(pamh, pam_error);
if (pam_end(pamh, ret) != PAM_SUCCESS) {
message("Failed to terminate PAM\n");
return AuthError;
}
if (strcmp((const char *)pam_item, user)) {
pam_end(pamh, PAM_SUCCESS); /* maybe use PAM_AUTH_ERR? */
return AuthBad;
}
pam_error = pam_setcred(pamh, PAM_REFRESH_CRED);
/* ignore errors on refresh credentials. If this did not work we use the old ones. */
pam_end(pamh, PAM_SUCCESS);
// openlog("kcheckpass", LOG_PID, LOG_AUTH);
// PAM_data.conv = conv;
// if (strcmp(method, "classic")) {
// sprintf(pservb, "%.31s-%.31s", KSCREENSAVER_PAM_SERVICE, method);
// pam_service = pservb;
// } else {
// /* PAM_data.classic = 1; */
// pam_service = KSCREENSAVER_PAM_SERVICE;
// }
// pam_error = pam_start(pam_service, user, &PAM_conversation, &pamh);
// if (pam_error != PAM_SUCCESS) {
// return AuthError;
// }
// tty = ttyname(0);
// if (!tty) {
// tty = getenv("DISPLAY");
// }
// pam_error = pam_set_item(pamh, PAM_TTY, tty);
// if (pam_error != PAM_SUCCESS) {
// pam_end(pamh, pam_error);
// return AuthError;
// }
//#ifdef PAM_FAIL_DELAY
// pam_set_item(pamh, PAM_FAIL_DELAY, (void *)fail_delay);
//#endif
// pam_error = pam_authenticate(pamh, 0);
// if (pam_error != PAM_SUCCESS) {
// if (PAM_data.abort) {
// PAM_data.abort = 0;
// pam_end(pamh, pam_error);
// return AuthAbort;
// }
// pam_end(pamh, pam_error);
// switch (pam_error) {
// case PAM_USER_UNKNOWN:
// case PAM_AUTH_ERR:
// case PAM_MAXTRIES: /* should handle this better ... */
// case PAM_AUTHINFO_UNAVAIL: /* returned for unknown users ... bogus */
// return AuthBad;
// default:
// return AuthError;
// }
// }
// /* just in case some module is stupid enough to ignore a preset PAM_USER */
// pam_error = pam_get_item(pamh, PAM_USER, &pam_item);
// if (pam_error != PAM_SUCCESS) {
// pam_end(pamh, pam_error);
// return AuthError;
// }
// if (strcmp((const char *)pam_item, user)) {
// pam_end(pamh, PAM_SUCCESS); /* maybe use PAM_AUTH_ERR? */
// return AuthBad;
// }
// pam_error = pam_setcred(pamh, PAM_REFRESH_CRED);
// /* ignore errors on refresh credentials. If this did not work we use the old ones. */
// pam_end(pamh, PAM_SUCCESS);
return AuthOk;
}

6
debian/changelog vendored

@ -1,5 +1,5 @@
cutefish-screenlocker (0.5) UNRELEASED; urgency=high
cutefish-screenlocker (0.5.1-1) UNRELEASED; urgency=high
* Initial release (CutefishOS) <support@cutefishos.com>
* Update 0.5.1 (CutefishOS) <support@cutefishos.com>
-- CutefishOS Packaging Team <support@cutefishos.com> Thu, 16 Sep 2021 02:31:42 +0800
-- CutefishOS Packaging Team <support@cutefishos.com> Tue, 12 Oct 2021 09:27:42 +0800

@ -2,12 +2,15 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
include_directories( ${UNIXAUTH_INCLUDE_DIRS} )
set(PROJECT_SOURCES
main.cpp
application.cpp
authenticator.cpp
kcheckpass-enums.h
fixx11h.h
pamauthentication.cpp
qml.qrc
)
@ -24,6 +27,8 @@ target_link_libraries(cutefish-screenlocker
Qt5::Quick
${X11_LIBRARIES}
${UNIXAUTH_LIBRARIES}
${SOCKET_LIBRARIES}
)
install(TARGETS cutefish-screenlocker RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

@ -64,6 +64,7 @@ public:
Application::Application(int &argc, char **argv)
: QGuiApplication(argc, argv)
, m_authenticator(new Authenticator(AuthenticationMode::Direct, this))
, m_pam(new PamAuthentication)
{
// It's a queued connection to give the QML part time to eventually execute code connected to Authenticator::succeeded if any
connect(m_authenticator, &Authenticator::succeeded, this, &Application::onSucceeded, Qt::QueuedConnection);
@ -102,6 +103,17 @@ void Application::initialViewSetup()
desktopResized();
}
void Application::login(const QString &token)
{
bool success = m_pam->verify(token);
if (success) {
onSucceeded();
} else {
qDebug() << "error";
}
}
void Application::desktopResized()
{
const int nScreens = screens().count();
@ -119,6 +131,7 @@ void Application::desktopResized()
// engine stuff
QQmlContext *context = view->engine()->rootContext();
context->setContextProperty(QStringLiteral("authenticator"), m_authenticator);
context->setContextProperty(QStringLiteral("App"), this);
view->setSource(QUrl("qrc:/qml/LockScreen.qml"));
view->setResizeMode(QQuickView::SizeRootObjectToView);
@ -127,13 +140,13 @@ void Application::desktopResized()
auto screen = QGuiApplication::screens()[i];
view->setGeometry(screen->geometry());
if (!m_testing) {
if (QX11Info::isPlatformX11()) {
view->setFlags(Qt::X11BypassWindowManagerHint);
} else {
view->setFlags(Qt::FramelessWindowHint);
}
}
// if (!m_testing) {
// if (QX11Info::isPlatformX11()) {
// view->setFlags(Qt::X11BypassWindowManagerHint);
// } else {
// view->setFlags(Qt::FramelessWindowHint);
// }
// }
// overwrite the factory set by kdeclarative
// auto oldFactory = view->engine()->networkAccessManagerFactory();

@ -25,6 +25,7 @@
#include <QVariantAnimation>
#include "authenticator.h"
#include "pamauthentication.h"
class Application : public QGuiApplication
{
@ -36,6 +37,8 @@ public:
void initialViewSetup();
Q_INVOKABLE void login(const QString &token);
public slots:
void desktopResized();
void onScreenAdded(QScreen *screen);
@ -57,6 +60,8 @@ private:
Authenticator *m_authenticator;
QList<QQuickView *> m_views;
PamAuthentication *m_pam;
bool m_testing = false;
};

@ -43,6 +43,7 @@ Authenticator::Authenticator(AuthenticationMode mode, QObject *parent)
, m_graceLockTimer(new QTimer(this))
, m_checkPass(nullptr)
{
m_pamAuth = new PamAuthentication;
m_graceLockTimer->setSingleShot(true);
m_graceLockTimer->setInterval(1500);
connect(m_graceLockTimer, &QTimer::timeout, this, &Authenticator::graceLockedChanged);

@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define AUTHENTICATOR_H
#include <QObject>
#include "pamauthentication.h"
class QSocketNotifier;
class QTimer;
@ -55,6 +56,8 @@ private:
void setupCheckPass();
QTimer *m_graceLockTimer;
KCheckPass *m_checkPass;
PamAuthentication *m_pamAuth;
};
class KCheckPass : public QObject
@ -106,6 +109,7 @@ private:
int m_fd;
bool m_ready = false;
AuthenticationMode m_mode;
};
#endif

@ -0,0 +1,125 @@
/*
* Copyright (C) 2021 CutefishOS Team
* Copyright (C) 2014 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author : Arto Jalkanen <ajalkane@gmail.com>
*/
#include "pamauthentication.h"
#include <QDebug>
// PAM
#include <security/pam_appl.h>
PamAuthentication::PamAuthentication(QObject *parent)
: QObject(parent)
{
m_userName = std::getenv("USER");
}
bool PamAuthentication::verify(const QString &password)
{
pam_handle *pamHandle = 0;
if (!initPam(&pamHandle)) {
qDebug() << Q_FUNC_INFO << "Pam init failed";
return false;
}
m_password = password;
int status = pam_authenticate(pamHandle, 0);
qDebug() << Q_FUNC_INFO << "Pam authenticate status" << status << pam_strerror(pamHandle, status);
if (status == PAM_SUCCESS) {
status = validateAccount(pamHandle);
}
pam_end(pamHandle, status);
m_password.clear();
return status == PAM_SUCCESS;
}
bool PamAuthentication::initPam(pam_handle **pamHandle)
{
pam_conv conversation;
conversation.conv = pamConv;
conversation.appdata_ptr = static_cast<void *>(this);
return pam_start("cutefishos", m_userName.toLocal8Bit().data(),
&conversation, pamHandle) == PAM_SUCCESS;
}
int PamAuthentication::validateAccount(pam_handle *pamHandle)
{
// This makes sure account and password are still valid
int status = pam_acct_mgmt(pamHandle, 0);
qDebug() << Q_FUNC_INFO << "pam_acct_mgmt: " << status << pam_strerror(pamHandle, status);
// Placeholders for some common errors
// IMPROVE: it'd be good to let user know reason for failure
switch (status) {
case PAM_SUCCESS:
break;
case PAM_USER_UNKNOWN:
break;
case PAM_ACCT_EXPIRED:
break;
case PAM_NEW_AUTHTOK_REQD:
break;
}
return status;
}
int PamAuthentication::pamConv(int num_msg, const pam_message **msg, pam_response **resp, void *appdata_ptr)
{
if (num_msg <= 0) {
return PAM_CONV_ERR;
}
*resp = static_cast<pam_response *>(calloc(num_msg, sizeof(pam_response)));
PamAuthentication *self = static_cast<PamAuthentication *>(appdata_ptr);
for (int count = 0; count < num_msg; ++count) {
switch (msg[count]->msg_style) {
case PAM_PROMPT_ECHO_ON: {
qDebug() << Q_FUNC_INFO << "PAM_PROMPT_ECHO_ON received";
resp[count]->resp = strdup(self->m_password.toLocal8Bit().data());
resp[count]->resp_retcode = 0;
break;
}
case PAM_PROMPT_ECHO_OFF: {
qDebug() << Q_FUNC_INFO << "PAM_PROMPT_ECHO_OFF received";
resp[count]->resp = strdup(self->m_password.toLocal8Bit().data());
resp[count]->resp_retcode = 0;
break;
}
case PAM_TEXT_INFO: {
QString message(msg[count]->msg);
qDebug() << Q_FUNC_INFO << "PAM_TEXT_INFO received" << message;
break;
}
case PAM_AUTHTOK: {
qDebug() << Q_FUNC_INFO << "PAM_AUTHTOK received";
break;
}
default: {
qDebug() << Q_FUNC_INFO << "Other PAM msg received: " << msg[count]->msg_style;
}
}
}
return PAM_SUCCESS;
}

@ -0,0 +1,50 @@
/*
* Copyright (C) 2021 CutefishOS Team
* Copyright (C) 2014 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Author : Arto Jalkanen <ajalkane@gmail.com>
*/
#ifndef PAMAUTHENTICATION_H
#define PAMAUTHENTICATION_H
#include <QObject>
// Forward declarations
struct pam_handle;
struct pam_message;
struct pam_response;
class PamAuthentication : public QObject
{
Q_OBJECT
public:
explicit PamAuthentication(QObject *parent = nullptr);
Q_INVOKABLE bool verify(const QString &password);
private:
bool initPam(pam_handle **pamHandle);
int validateAccount(pam_handle *pamHandle);
static int pamConv(int num_msg, const pam_message **msg,
pam_response **resp, void *appdata_ptr);
private:
QString m_userName;
QString m_password;
};
#endif // PAMAUTHENTICATION_H

@ -334,7 +334,9 @@ Item {
return
}
authenticator.tryUnlock(password.text)
App.login(password.text)
// authenticator.tryUnlock(password.text)
}
Timer {

Loading…
Cancel
Save