Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lxqt-admin-user-password - external gui utility for changing pass… #132

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD" OR ${CMAKE_SYSTEM_NAME} MATCHES "NetBS
message(WARNING "${CMAKE_SYSTEM_NAME} is not supported by lxqt-admin-time")
else()
add_subdirectory(lxqt-admin-user)
add_subdirectory(lxqt-admin-user-password)
add_subdirectory(lxqt-admin-time)
endif()
54 changes: 54 additions & 0 deletions lxqt-admin-user-password/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
project(lxqt-admin-user-password)

# build static helper class first
include_directories (
${CMAKE_CURRENT_BINARY_DIR}
)

# define sources
file(GLOB HEADERS *.h)
file(GLOB UI_FORMS *.ui)
file(GLOB SOURCES *.cpp)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(ALL_SOURCES
${SOURCES}
${UI_FORMS}
${HEADERS}
)

add_definitions(-DPROJECT_NAME="${PROJECT_NAME}")

# Translations **********************************
lxqt_translate_ts(muser_QM_FILES
UPDATE_TRANSLATIONS YES
UPDATE OPTIONS
SOURCES
${MOCS}
${SOURCES}
${UI_FORMS}
INSTALL_DIR
"${LXQT_TRANSLATIONS_DIR}/${PROJECT_NAME}"
PULL_TRANSLATIONS NO
)

lxqt_app_translation_loader(lxqt-admin-user-password_QM_LOADER ${PROJECT_NAME})
#************************************************

add_executable(lxqt-admin-user-password
${ALL_SOURCES}
${lxqt-admin-user-password_QM_FILES}
${lxqt-admin-user-password_QM_LOADER}
)

target_link_libraries(lxqt-admin-user-password
KF5::WindowSystem
Qt5::Widgets
lxqt
pam
)

install(TARGETS lxqt-admin-user-password RUNTIME DESTINATION bin)
254 changes: 254 additions & 0 deletions lxqt-admin-user-password/changepassworddialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
#include "changepassworddialog.h"
#include "ui_changepassworddialog.h"

#include <security/pam_appl.h>

#include <QMessageBox>
#include <QLabel>
#include <QLineEdit>

#include <QDebug>

int ChangePasswordDialog::conversation(int num_msg,
const struct pam_message **msg,
struct pam_response **resp,
void *appdata_ptr)
{
*resp = 0;
ChangePasswordDialog *dialog = 0;
if (!(num_msg && (dialog = (ChangePasswordDialog *) appdata_ptr) && ! dialog->_userAbort))
return PAM_CONV_ERR;

int answerSize = num_msg * sizeof(struct pam_response);
struct pam_response *answer = 0;

if (!(answer = (struct pam_response *) malloc(answerSize)))
return PAM_BUF_ERR;

memset(answer, 0, answerSize);

bool labelAdded = false;
for (int i = 0; i < num_msg; i++)
{
QString message = QString::fromLocal8Bit(msg[i]->msg);
switch (msg[i]->msg_style)
{
case PAM_PROMPT_ECHO_OFF:
{
labelAdded = true;
dialog->addLabel(message, true);
}
break;
case PAM_PROMPT_ECHO_ON:
{
labelAdded = true;
dialog->addLabel(message, false);
}
break;
case PAM_ERROR_MSG:
dialog->addWarning(message);
break;
case PAM_TEXT_INFO :
dialog->addMessage(message);
break;
default:
{
free(answer);
return PAM_CONV_ERR;
}
}
}

if (!labelAdded)
{
*resp = answer;
return PAM_SUCCESS;
}

dialog->showWarnings();
dialog->showMessages();

if (!(dialog->exec() == QDialog::Accepted))
{
dialog->_userAbort = true;
free(answer);
return PAM_CONV_ERR;
}

for (int i = 0, j = 0; i < num_msg; i++)
{
switch (msg[i]->msg_style)
{
case PAM_PROMPT_ECHO_OFF:
case PAM_PROMPT_ECHO_ON:
{
char *str = strdup(qPrintable(dialog->values().at(j)));
j++;
if (!str)
{
for (int k = 0; k < i; k++)
free(answer[k].resp);
free(answer);
return PAM_BUF_ERR;
}
answer[i].resp = str;
}
break;
default :
break;
}
}

*resp = answer;
return PAM_SUCCESS;
}

ChangePasswordDialog::ChangePasswordDialog(QWidget *parent)
: QDialog(parent)
, _ui(new Ui::ChangePasswordDialog)
, _userAbort(false)
{
_ui->setupUi(this);
}

ChangePasswordDialog::~ChangePasswordDialog()
{
delete _ui;
}

const QString &ChangePasswordDialog::user() const
{
return _user;
}

void ChangePasswordDialog::setUser(const QString &user)
{
if (_user == user)
return;

_user = user;
setWindowTitle(tr("Change password for user \"%1\"").arg(_user));
}

void ChangePasswordDialog::addWarning(const QString &warning)
{
_warnings.append(warning);
}

void ChangePasswordDialog::addMessage(const QString &message)
{
_messages.append(message);
}

void ChangePasswordDialog::addLabel(const QString &textLabel, bool isShadow)
{
QLabel *label = new QLabel();;
QLineEdit *lineEdit = new QLineEdit();

label->setText(textLabel);
lineEdit->setEchoMode(isShadow ? QLineEdit::Password : QLineEdit::Normal);

_ui->_verticalLayout->addWidget(label);
_ui->_verticalLayout->addWidget(lineEdit);
}

const QList<QString> &ChangePasswordDialog::values() const
{
return _values;
}

bool ChangePasswordDialog::changePassword()
{
if (_user.isEmpty())
return false;

_userAbort = false;

pam_handle_t *pamh = NULL;

pam_conv pam_conversation;
pam_conversation.conv = ChangePasswordDialog::conversation;
pam_conversation.appdata_ptr = (void *) this;

int result = 0;

result = pam_start("password", qPrintable(_user), &pam_conversation, &pamh);

if (result != PAM_SUCCESS)
{
QMessageBox::critical(parentWidget(), tr("PAM transaction"), tr("PAM transaction not started.\nError code: %1").arg(result));
return false;
}

bool isChanged = ((result = pam_chauthtok(pamh, 0)) == PAM_SUCCESS);

showWarnings();
showMessages();

if ((result = pam_end(pamh, result)) != PAM_SUCCESS)
QMessageBox::critical(parentWidget(), tr("PAM transaction"), tr("PAM transaction not finished.\nError code: %1").arg(result));

return isChanged;
}

void ChangePasswordDialog::reset()
{
int size = _ui->_verticalLayout->count();
for (int i = 0; i < size; i++)
{
QLayoutItem *layoutItem = _ui->_verticalLayout->itemAt(0);
QWidget *widget = layoutItem->widget();
_ui->_verticalLayout->removeItem(layoutItem);
if (widget)
delete widget;
}
}

void ChangePasswordDialog::showMessages()
{
if (_messages.size())
{
QMessageBox::information(parentWidget(), windowTitle(), _messages.join(QStringLiteral("\n")));
_messages.clear();
}
}

void ChangePasswordDialog::showWarnings()
{
if (_warnings.size())
{
QMessageBox::warning(parentWidget(), windowTitle(), _warnings.join(QStringLiteral("\n")));
_warnings.clear();
}
}

void ChangePasswordDialog::showEvent(QShowEvent *event)
{
if (!_ui->_verticalLayout->count())
return;
_ui->_verticalLayout->addStretch(1);
QDialog::showEvent(event);
_ui->_verticalLayout->itemAt(1)->widget()->setFocus();

}

void ChangePasswordDialog::accept()
{
_values.clear();

int size = _ui->_verticalLayout->count();
for (int i = 0; (i + 1) < size; i += 2)
{
QLineEdit *lineEdit = qobject_cast<QLineEdit *>(_ui->_verticalLayout->itemAt(i + 1)->widget());
if (lineEdit)
_values.append( lineEdit->text() );
}
reset();
QDialog::accept();
}

void ChangePasswordDialog::reject()
{
reset();
QDialog::reject();
}
54 changes: 54 additions & 0 deletions lxqt-admin-user-password/changepassworddialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#ifndef CHANGEPASSWORDDIALOG_H
#define CHANGEPASSWORDDIALOG_H

#include <QDialog>

namespace Ui {
class ChangePasswordDialog;
}

class ChangePasswordDialog : public QDialog
{
Q_OBJECT

public:
static int conversation(int, const struct pam_message**, struct pam_response**, void *);

ChangePasswordDialog(QWidget */*parent*/ = 0);
virtual ~ChangePasswordDialog();

const QString &user() const;
void setUser(const QString &user);

void addWarning(const QString &);
void addMessage(const QString &);
void addLabel(const QString &, bool);

const QList<QString> &values() const;
bool changePassword();

protected:
void reset();
void showMessages();
void showWarnings();

virtual void showEvent(QShowEvent *event);

public slots:
virtual void accept();
virtual void reject();

protected:
Ui::ChangePasswordDialog *_ui;

bool _userAbort;

QString _user;

QStringList _warnings;
QStringList _messages;
QList<bool> _shadows;
QList<QString> _values;
};

#endif // CHANGEPASSWORDDIALOG_H
Loading