ukui-control-center/ukui-control-center-3.1.2-fix-password-changes-for-this-user-and-for-other-use.patch

1895 lines
61 KiB
Diff
Raw Normal View History

From d345bc5b0688c93f1942e38a0bf03eca9dbb0001 Mon Sep 17 00:00:00 2001
From: huayadong <huayadong@kylinos.cn>
Date: Fri, 9 Jun 2023 10:54:52 +0800
Subject: [PATCH] fix-password-changes-for-this-user-and-for-other-use
---
changeOtherUserPwd/run-passwd2.cpp | 5 +
changeUserPwd/run-passwd.cpp | 4 +
checkUserPwdWithPAM/checkUserPwd/auth-pam.cpp | 343 ---------
checkUserPwdWithPAM/checkUserPwd/auth-pam.h | 59 --
checkUserPwdWithPAM/checkUserPwd/auth.h | 62 --
.../checkUserPwd/checkUserPwd.pro | 38 -
checkUserPwdWithPAM/checkUserPwd/main.cpp | 20 -
checkUserPwdWithPAM/checkUserPwd/widget.cpp | 61 --
checkUserPwdWithPAM/checkUserPwd/widget.h | 29 -
checkUserPwdWithPAM/checkUserPwdWithPAM.pro | 41 +-
.../childCheckPwdWithPAM.pro | 39 -
.../childCheckPwdWithPAM/main.cpp | 166 -----
checkUserPwdWithPAM/conf/control-center | 11 -
checkUserPwdWithPAM/main.cpp | 81 ++
checkUserPwdWithPAM/run-passwd.cpp | 704 ++++++++++++++++++
checkUserPwdWithPAM/run-passwd.h | 34 +
plugins/account/userinfo/changeuserpwd.cpp | 3 +-
plugins/account/userinfo/pwdcheckthread.cpp | 2 +-
translate_generation.sh | 2 +-
19 files changed, 867 insertions(+), 837 deletions(-)
delete mode 100644 checkUserPwdWithPAM/checkUserPwd/auth-pam.cpp
delete mode 100644 checkUserPwdWithPAM/checkUserPwd/auth-pam.h
delete mode 100644 checkUserPwdWithPAM/checkUserPwd/auth.h
delete mode 100644 checkUserPwdWithPAM/checkUserPwd/checkUserPwd.pro
delete mode 100644 checkUserPwdWithPAM/checkUserPwd/main.cpp
delete mode 100644 checkUserPwdWithPAM/checkUserPwd/widget.cpp
delete mode 100644 checkUserPwdWithPAM/checkUserPwd/widget.h
delete mode 100644 checkUserPwdWithPAM/childCheckPwdWithPAM/childCheckPwdWithPAM.pro
delete mode 100644 checkUserPwdWithPAM/childCheckPwdWithPAM/main.cpp
delete mode 100644 checkUserPwdWithPAM/conf/control-center
create mode 100644 checkUserPwdWithPAM/main.cpp
create mode 100644 checkUserPwdWithPAM/run-passwd.cpp
create mode 100644 checkUserPwdWithPAM/run-passwd.h
diff --git a/changeOtherUserPwd/run-passwd2.cpp b/changeOtherUserPwd/run-passwd2.cpp
index 29c1901..483cfaa 100644
--- a/changeOtherUserPwd/run-passwd2.cpp
+++ b/changeOtherUserPwd/run-passwd2.cpp
@@ -284,6 +284,11 @@ static gboolean io_watch_stdout (GIOChannel *source, GIOCondition condition, Pas
/* Pop retyped password from queue and into IO channel */
io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
+ if (passwd_handler->chpasswd_cb)
+ passwd_handler->chpasswd_cb (passwd_handler,
+ NULL,
+ passwd_handler->chpasswd_cb_data);
+
reinit = TRUE;
}
break;
diff --git a/changeUserPwd/run-passwd.cpp b/changeUserPwd/run-passwd.cpp
index 3b416ec..2700f78 100644
--- a/changeUserPwd/run-passwd.cpp
+++ b/changeUserPwd/run-passwd.cpp
@@ -286,6 +286,10 @@ static gboolean io_watch_stdout (GIOChannel *source, GIOCondition condition, Pas
io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
reinit = TRUE;
+ if (passwd_handler->chpasswd_cb)
+ passwd_handler->chpasswd_cb (passwd_handler,
+ NULL,
+ passwd_handler->chpasswd_cb_data);
}
break;
case PASSWD_STATE_RETYPE:
diff --git a/checkUserPwdWithPAM/checkUserPwd/auth-pam.cpp b/checkUserPwdWithPAM/checkUserPwd/auth-pam.cpp
deleted file mode 100644
index 9695b54..0000000
--- a/checkUserPwdWithPAM/checkUserPwd/auth-pam.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * 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/>.
- *
-**/
-#include "auth-pam.h"
-#include <string.h>
-#include <QDebug>
-#include <sys/prctl.h>
-#include <unistd.h>
-#include <wait.h>
-
-#include <QTimer>
-
-
-#define PAM_SERVICE_NAME "control-center"
-
-//通信管道的文件描述符
-int toParent[2], toChild[2];
-
-static void writeData(int fd, const void *buf, ssize_t count);
-static void writeString(int fd, const char *data);
-static int readData(int fd, void *buf, size_t count);
-static char * readString(int fd);
-static int pam_conversation(int msgLength, const struct pam_message **msg,
- PAM_RESPONSE **resp, void *appData);
-static void sigchld_handler(int signo);
-
-AuthPAM::AuthPAM(QObject *parent)
- : Auth(parent),
- pid(0),
- nPrompts(0),
- _isAuthenticated(false),
- _isAuthenticating(false)
-{
- signal(SIGCHLD, sigchld_handler);
-}
-
-void AuthPAM::authenticate(const QString &userName, const QString &userPwd)
-{
- stopAuth();
-
- if(pipe(toParent) || pipe(toChild))
- qDebug()<< "create pipe failed: " << strerror(errno);
- if((pid = fork()) < 0)
- {
- qDebug() << "fork error: " << strerror(errno);
- }
- else if(pid == 0)
- {
- int arg1_int = toParent[1];
- int arg2_int = toChild[0];
- char arg1[128];
- char arg2[128];
- snprintf(arg1,128,"%d",arg1_int);
- snprintf(arg2,128,"%d",arg2_int);
- //_authenticate(userName.toLocal8Bit().data());
- prctl(PR_SET_PDEATHSIG,SIGHUP);
- execlp ("childCheckpwdwithPAM",
- "childCheckpwdwithPAM",
- arg1, arg2,userName.toLocal8Bit().data(), NULL);
- _exit (EXIT_FAILURE);
- }
- else
- {
- _isAuthenticating = true;
- notifier = new QSocketNotifier(toParent[0], QSocketNotifier::Read);
- connect(notifier, &QSocketNotifier::activated, this, &AuthPAM::onSockRead);
- }
-
- QTimer::singleShot(100, this, [=]{respond(userPwd);});
-
-}
-
-void AuthPAM::stopAuth()
-{
-// qDebug()<<"pppppppppppppppppid = "<<pid;
- if(pid != 0)
- {
- messageList.clear();
- responseList.clear();
- _isAuthenticating = false;
- _isAuthenticated = false;
- nPrompts = 0;
-
- ::kill(pid, SIGKILL);
-
- pid = 0;
- }
-}
-
-void AuthPAM::respond(const QString &response)
-{
- nPrompts--;
- responseList.push_back(response);
-
-// for(auto msg : messageList)
-// qDebug() << msg.msg;
-// qDebug() << responseList;
-// qDebug() << nPrompts;
-
- if(nPrompts == 0)
- {
- //发送响应到子进程
- int j = 0;
- PAM_RESPONSE *resp = (PAM_RESPONSE*)calloc(messageList.size(), sizeof(PAM_RESPONSE));
- //响应的数量和消息的数量一致如果消息类型不是PROMPT则响应是空的
- for(int i = 0; i < messageList.size(); i++)
- {
- struct pam_message message = messageList[i];
- PAM_RESPONSE *r = &resp[i];
- if(message.msg_style == PAM_PROMPT_ECHO_OFF
- || message.msg_style == PAM_PROMPT_ECHO_ON)
- {
- int respLength = responseList[j].length() + 1;
- r->resp = (char *)malloc(sizeof(char) * respLength);
- memcpy(r->resp, responseList[j].toLocal8Bit().data(), respLength);
- j++;
- }
- }
- _respond(resp);
- free(resp);
- resp = NULL;
- messageList.clear();
- responseList.clear();
- }
-}
-
-bool AuthPAM::isAuthenticated()
-{
- return _isAuthenticated;
-}
-
-bool AuthPAM::isAuthenticating()
-{
- return _isAuthenticating;
-}
-
-
-void AuthPAM::onSockRead()
-{
-// qDebug() << "has message";
- int msgLength;
- int authComplete;
- readData(toParent[0], &authComplete, sizeof(authComplete));
-
- if(authComplete)
- {
- int authRet;
- if(readData(toParent[0], (void*)&authRet, sizeof(authRet)) <= 0)
- qDebug() << "get authentication result failed: " << strerror(errno);
-// qDebug() << "result: " << authRet;
- _isAuthenticated = (authRet == PAM_SUCCESS);
- _isAuthenticating = false;
- Q_EMIT authenticateComplete();
-
- }
- else
- {
- readData(toParent[0], &msgLength, sizeof(msgLength));
-// qDebug() << "message length: " << msgLength;
-
- for(int i = 0; i < msgLength; i++)
- {
- //读取message
- struct pam_message message;
- readData(toParent[0], &message.msg_style, sizeof(message.msg_style));
- message.msg = readString(toParent[0]);
-
-// qDebug() << message.msg;
-
- messageList.push_back(message);
-
- switch (message.msg_style)
- {
- case PAM_PROMPT_ECHO_OFF:
- nPrompts++;
- Q_EMIT showPrompt(message.msg, Auth::PromptTypeSecret);
- break;
- case PAM_PROMPT_ECHO_ON:
- nPrompts++;
- Q_EMIT showPrompt(message.msg, Auth::PromptTypeQuestion);
- break;
- case PAM_ERROR_MSG:
- Q_EMIT showMessage(message.msg, Auth::MessageTypeInfo);
- break;
- case PAM_TEXT_INFO:
- Q_EMIT showMessage(message.msg, Auth::MessageTypeError);
- break;
- }
- }
-
- if(nPrompts == 0)
- {
- //不需要响应,发送一个空的
- PAM_RESPONSE *response = (PAM_RESPONSE*)calloc(messageList.size(), sizeof(PAM_RESPONSE));
- _respond(response);
- free(response);
- response = NULL;
- messageList.clear();
- }
- }
-}
-
-static void
-writeData(int fd, const void *buf, ssize_t count)
-{
- if(write(fd, buf, count) != count)
- qDebug() << "write to parent failed: " << strerror(errno);
-}
-
-static void
-writeString(int fd, const char *data)
-{
- int length = data ? strlen(data) : -1;
- writeData(fd, &length, sizeof(length));
- if(data)
- writeData(fd, data, sizeof(char) * length);
-}
-
-static int
-readData(int fd, void *buf, size_t count)
-{
- ssize_t nRead = read(fd, buf, count);
- if(nRead < 0)
- qDebug() << "read data failed: " << strerror(errno);
- return nRead;
-}
-
-static char *
-readString(int fd)
-{
- int length;
-
- if(readData(fd, &length, sizeof(length)) <= 0)
- return NULL;
- if(length <= 0)
- return NULL;
-
- char *value = (char *)malloc(sizeof(char) * (length + 1));
- readData(fd, value, length);
- value[length] = '\0';
-
- return value;
-}
-
-void AuthPAM::_authenticate(const char *userName)
-{
-// qDebug() << "authenticate " << userName;
-
- pam_handle_t *pamh = NULL;
- char *newUser;
- int ret;
- int authRet;
- struct pam_conv conv;
-
- conv.conv = pam_conversation;
- conv.appdata_ptr = NULL;
-
- ret = pam_start(PAM_SERVICE_NAME, userName, &conv, &pamh);
- if(ret != PAM_SUCCESS)
- {
- qDebug() << "failed to start PAM: " << pam_strerror(NULL, ret);
- }
-
- authRet = pam_authenticate(pamh, 0);
-
- ret = pam_get_item(pamh, PAM_USER, (const void **)&newUser);
- if(ret != PAM_SUCCESS)
- {
- pam_end(pamh, 0);
- qDebug() << "failed to get username";
- }
- free(newUser);
- newUser = NULL;
-// fprintf(stderr, "authentication result: %d\n", authRet);
-
- // 发送认证结果
- int authComplete = 1;
- writeData(toParent[1], (const void*)&authComplete, sizeof(authComplete));
- writeData(toParent[1], (const void *)&authRet, sizeof(authRet));
-// qDebug() << "--- 认证完成";
- _exit(EXIT_SUCCESS);
-}
-
-void AuthPAM::_respond(const PAM_RESPONSE *response)
-{
- for(int i = 0; i < messageList.size(); i++)
- {
- const PAM_RESPONSE *resp = &response[i];
- writeData(toChild[1], (const void *)&resp->resp_retcode,
- sizeof(resp->resp_retcode));
- writeString(toChild[1], resp->resp);
- }
-}
-
-
-static int
-pam_conversation(int msgLength, const struct pam_message **msg,
- PAM_RESPONSE **resp, void */*appData*/)
-{
- PAM_RESPONSE *response = (PAM_RESPONSE*)calloc(msgLength,sizeof(PAM_RESPONSE));
-
- int authComplete = 0;
- writeData(toParent[1], (const void*)&authComplete, sizeof(authComplete));
- writeData(toParent[1], (const void*)&msgLength, sizeof(msgLength));
- //发送pam消息
- for(int i = 0; i < msgLength; i++)
- {
- const struct pam_message *m = msg[i];
- writeData(toParent[1], (const void *)&m->msg_style, sizeof(m->msg_style));
- writeString(toParent[1], m->msg);
- }
- //读取响应
- for(int i = 0; i < msgLength; i++)
- {
- PAM_RESPONSE *r = &response[i];
- readData(toChild[0], &r->resp_retcode, sizeof(r->resp_retcode));
- r->resp = readString(toChild[0]);
- }
- *resp = response;
- return PAM_SUCCESS;
-}
-
-void sigchld_handler(int signo)
-{
- if(signo == SIGCHLD)
- {
- ::waitpid(-1, NULL, WNOHANG);
- }
-}
diff --git a/checkUserPwdWithPAM/checkUserPwd/auth-pam.h b/checkUserPwdWithPAM/checkUserPwd/auth-pam.h
deleted file mode 100644
index 9497351..0000000
--- a/checkUserPwdWithPAM/checkUserPwd/auth-pam.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * 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/>.
- *
-**/
-#ifndef AUTHPAM_H
-#define AUTHPAM_H
-#include "auth.h"
-#include <QSocketNotifier>
-#include <QList>
-
-#include <security/pam_appl.h>
-
-typedef struct pam_message PAM_MESSAGE;
-typedef struct pam_response PAM_RESPONSE;
-
-class AuthPAM : public Auth
-{
- Q_OBJECT
-public:
- AuthPAM(QObject *parent = nullptr);
-
- void authenticate(const QString &userName, const QString &userPwd);
- void stopAuth();
- void respond(const QString &response);
- bool isAuthenticated();
- bool isAuthenticating();
-
-private:
- void _authenticate(const char *userName);
- void _respond(const struct pam_response *response);
-
-private Q_SLOTS:
- void onSockRead();
-
-private:
- QString userName;
- pid_t pid;
- QSocketNotifier *notifier;
- int nPrompts;
- QStringList responseList;
- QList<PAM_MESSAGE> messageList;
- bool _isAuthenticated; //认证结果
- bool _isAuthenticating;
-};
-
-#endif // AUTHPAM_H
diff --git a/checkUserPwdWithPAM/checkUserPwd/auth.h b/checkUserPwdWithPAM/checkUserPwd/auth.h
deleted file mode 100644
index 22d9f23..0000000
--- a/checkUserPwdWithPAM/checkUserPwd/auth.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3, or (at your option)
- * any later version.
- *
- * 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/>.
- *
-**/
-#ifndef AUTH_H
-#define AUTH_H
-
-#ifndef QT_NO_KEYWORDS
-#define QT_NO_KEYWORDS
-#endif
-
-#include <QObject>
-
-class Auth : public QObject
-{
- Q_OBJECT
-
- Q_ENUMS(PromptType MessageType)
-public:
- explicit Auth(QObject *parent = nullptr)
- : QObject(parent)
- {
-
- }
-
- enum PromptType {
- PromptTypeQuestion,
- PromptTypeSecret
- };
- enum MessageType {
- MessageTypeInfo,
- MessageTypeError
- };
-
-
-Q_SIGNALS:
- void showPrompt(const QString &prompt, Auth::PromptType type);
- void showMessage(const QString &message, Auth::MessageType type);
- void authenticateComplete();
-
-public:
- virtual void authenticate(const QString &userName, const QString &userPwd) = 0;
- virtual void stopAuth() = 0;
- virtual void respond(const QString &response) = 0;
- virtual bool isAuthenticating() = 0;
- virtual bool isAuthenticated() = 0;
-};
-
-#endif // AUTH_H
diff --git a/checkUserPwdWithPAM/checkUserPwd/checkUserPwd.pro b/checkUserPwdWithPAM/checkUserPwd/checkUserPwd.pro
deleted file mode 100644
index 8037587..0000000
--- a/checkUserPwdWithPAM/checkUserPwd/checkUserPwd.pro
+++ /dev/null
@@ -1,38 +0,0 @@
-QT += core
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-TARGET = checkUserPwd
-TEMPLATE = app
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-LIBS += -lpam
-
-SOURCES += \
- auth-pam.cpp \
- main.cpp \
- widget.cpp
-
-HEADERS += \
- auth-pam.h \
- auth.h \
- widget.h
-
-target.source += $$TARGET
-target.path = /usr/bin
-
-
-INSTALLS += \
- target \
diff --git a/checkUserPwdWithPAM/checkUserPwd/main.cpp b/checkUserPwdWithPAM/checkUserPwd/main.cpp
deleted file mode 100644
index 8f7dfc7..0000000
--- a/checkUserPwdWithPAM/checkUserPwd/main.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "widget.h"
-
-#include <QCoreApplication>
-
-#include <QDebug>
-
-int main(int argc, char *argv[])
-{
- QCoreApplication a(argc, argv);
-
-
- Widget w;
- if (argc == 3){
- w.pwdCheck(argv[1], argv[2]);
- } else {
- return 1;
- }
-
- return a.exec();
-}
diff --git a/checkUserPwdWithPAM/checkUserPwd/widget.cpp b/checkUserPwdWithPAM/checkUserPwd/widget.cpp
deleted file mode 100644
index 059333e..0000000
--- a/checkUserPwdWithPAM/checkUserPwd/widget.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-#include "widget.h"
-
-#include "auth-pam.h"
-
-#include <QDebug>
-
-
-Widget::Widget()
-{
-
- auth = new AuthPAM(this);
-
- accountlock = false;
-
- connect(auth, &Auth::showMessage, this, &Widget::onShowMessage);
- connect(auth, &Auth::showPrompt, this, &Widget::onShowPrompt);
- connect(auth, &Auth::authenticateComplete, this, &Widget::onAuthComplete);
-
-}
-
-Widget::~Widget()
-{
-
- auth->stopAuth();
-
- delete auth;
-}
-
-void Widget::pwdCheck(QString userName, QString userPwd){
- auth->authenticate(userName, userPwd);
-}
-
-void Widget::onShowMessage(const QString &message, Auth::MessageType type)
-{
-// qDebug() << "showMessage" << message;
- accountlock = true;
- printf("%s\n", message.toUtf8().data());
-}
-
-void Widget::onShowPrompt(const QString &prompt, Auth::PromptType type)
-{
-// qDebug() << "prompt: " << prompt;
-}
-
-void Widget::onAuthComplete()
-{
-
- if (!accountlock){
- if(auth->isAuthenticated()){
-// qDebug() << "Succes!\n";
-// printf("Succes!\n");
- } else {
- printf("Failed!\n");
-// qDebug() << "Failed!";
- }
- }
-
- exit(0);
-
-}
-
diff --git a/checkUserPwdWithPAM/checkUserPwd/widget.h b/checkUserPwdWithPAM/checkUserPwd/widget.h
deleted file mode 100644
index 86f0e8f..0000000
--- a/checkUserPwdWithPAM/checkUserPwd/widget.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef WIDGET_H
-#define WIDGET_H
-
-
-#include "auth-pam.h"
-
-
-class Widget : public QObject
-{
- Q_OBJECT
-
-public:
- Widget();
- ~Widget();
-
-public:
- void pwdCheck(QString userName, QString userPwd);
-
-private:
- Auth * auth;
-
- bool accountlock;
-
-private Q_SLOTS:
- void onShowMessage(const QString &message, Auth::MessageType type);
- void onShowPrompt(const QString &prompt, Auth::PromptType type);
- void onAuthComplete();
-};
-#endif // WIDGET_H
diff --git a/checkUserPwdWithPAM/checkUserPwdWithPAM.pro b/checkUserPwdWithPAM/checkUserPwdWithPAM.pro
index 9d6c015..97f51f0 100644
--- a/checkUserPwdWithPAM/checkUserPwdWithPAM.pro
+++ b/checkUserPwdWithPAM/checkUserPwdWithPAM.pro
@@ -1,7 +1,38 @@
-TEMPLATE = subdirs
+QT -= gui
-CONFIG += ordered
+TARGET = checkUserPwd
+TEMPLATE = app
-SUBDIRS = \
- childCheckPwdWithPAM \
- checkUserPwd \
+CONFIG += c++11
+CONFIG -= app_bundle
+
+# The following define makes your compiler emit warnings if you use
+# any Qt feature that has been marked deprecated (the exact warnings
+# depend on your compiler). Please consult the documentation of the
+# deprecated API in order to know how to port your code away from it.
+DEFINES += QT_DEPRECATED_WARNINGS
+
+
+##加载gio库和gio-unix库
+CONFIG += link_pkgconfig \
+ C++11
+PKGCONFIG += gio-2.0 \
+ gio-unix-2.0 \
+
+# You can also make your code fail to compile if it uses deprecated APIs.
+# In order to do so, uncomment the following line.
+# You can also select to disable deprecated APIs only up to a certain version of Qt.
+#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+target.source += $$TARGET
+target.path = /usr/bin
+INSTALLS += \
+ target \
+
+
+SOURCES += \
+ main.cpp \
+ run-passwd.cpp
+
+HEADERS += \
+ run-passwd.h
diff --git a/checkUserPwdWithPAM/childCheckPwdWithPAM/childCheckPwdWithPAM.pro b/checkUserPwdWithPAM/childCheckPwdWithPAM/childCheckPwdWithPAM.pro
deleted file mode 100644
index c2f5532..0000000
--- a/checkUserPwdWithPAM/childCheckPwdWithPAM/childCheckPwdWithPAM.pro
+++ /dev/null
@@ -1,39 +0,0 @@
-QT -= core
-QT -= gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-TARGET = childCheckpwdwithPAM
-TEMPLATE = app
-
-CONFIG += c++11
-
-# The following define makes your compiler emit warnings if you use
-# any Qt feature that has been marked deprecated (the exact warnings
-# depend on your compiler). Please consult the documentation of the
-# deprecated API in order to know how to port your code away from it.
-DEFINES += QT_DEPRECATED_WARNINGS
-
-# You can also make your code fail to compile if it uses deprecated APIs.
-# In order to do so, uncomment the following line.
-# You can also select to disable deprecated APIs only up to a certain version of Qt.
-#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
-LIBS += -lpam
-
-SOURCES += \
- main.cpp
-
-HEADERS +=
-
-
-cf.files += ../conf/control-center
-cf.path = /etc/pam.d/
-
-target.source += $$TARGET
-target.path = /usr/bin
-
-
-INSTALLS += \
- cf \
- target \
diff --git a/checkUserPwdWithPAM/childCheckPwdWithPAM/main.cpp b/checkUserPwdWithPAM/childCheckPwdWithPAM/main.cpp
deleted file mode 100644
index ed9d883..0000000
--- a/checkUserPwdWithPAM/childCheckPwdWithPAM/main.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <wait.h>
-#include <fcntl.h>
-#include <security/pam_appl.h>
-#include <sys/mman.h>
-static int toParent = 0;
-static int fromChild = 0;
-
-typedef struct pam_message PAM_MESSAGE;
-typedef struct pam_response PAM_RESPONSE;
-
-static void
-writeData(int fd, const void *buf, ssize_t count)
-{
- if(write(fd, buf, count) != count)
- printf("write to parent failed: %s\n",strerror(errno));
-}
-
-static void
-writeString(int fd, const char *data)
-{
- int length = data ? strlen(data) : -1;
- writeData(fd, &length, sizeof(length));
- if(data)
- writeData(fd, data, sizeof(char) * length);
-}
-
-static int
-readData(int fd, void *buf, size_t count)
-{
- ssize_t nRead = read(fd, buf, count);
- if(nRead < 0)
- printf("read data failed: %s\n",strerror(errno));
- return nRead;
-}
-
-static char *
-readString(int fd)
-{
- int length;
-
- if(readData(fd, &length, sizeof(length)) <= 0)
- return NULL;
- if(length <= 0)
- return NULL;
-
- char *value = (char *)malloc(sizeof(char) * (length + 1));
- readData(fd, value, length);
- value[length] = '\0';
-
- return value;
-}
-
-static int
-pam_conversation(int msgLength, const struct pam_message **msg,
- PAM_RESPONSE **resp, void */*appData*/)
-{
- PAM_RESPONSE *response = (PAM_RESPONSE*)calloc(msgLength,sizeof(PAM_RESPONSE));
-
- int authComplete = 0;
- writeData(toParent, (const void*)&authComplete, sizeof(authComplete));
- writeData(toParent, (const void*)&msgLength, sizeof(msgLength));
- //发送pam消息
- for(int i = 0; i < msgLength; i++)
- {
- const struct pam_message *m = msg[i];
- writeData(toParent, (const void *)&m->msg_style, sizeof(m->msg_style));
- writeString(toParent, m->msg);
- }
- //读取响应
- for(int i = 0; i < msgLength; i++)
- {
- PAM_RESPONSE *r = &response[i];
- readData(fromChild, &r->resp_retcode, sizeof(r->resp_retcode));
- r->resp = readString(fromChild);
- }
- *resp = response;
- return PAM_SUCCESS;
-}
-
-static void
-_authenticate(const char *userName)
-{
-// printf("authenticate %s\n",userName);
-
- pam_handle_t *pamh = NULL;
- char *newUser;
- int ret;
- int authRet;
- struct pam_conv conv;
-
- conv.conv = pam_conversation;
- conv.appdata_ptr = NULL;
-
- ret = pam_start("control-center", userName, &conv, &pamh);
- if(ret != PAM_SUCCESS)
- {
- printf("failed to start PAM: = %s\n", pam_strerror(NULL, ret));
- }
-
- authRet = pam_authenticate(pamh, 0);
-
- ret = pam_get_item(pamh, PAM_USER, (const void **)&newUser);
- if(ret != PAM_SUCCESS)
- {
- pam_end(pamh, 0);
- printf("failed to get username\n");
- }
- free(newUser);
- newUser = NULL;
-// fprintf(stderr, "authentication result: %d\n", authRet);
-
- // 发送认证结果
- int authComplete = 1;
- writeData(toParent, (const void*)&authComplete, sizeof(authComplete));
- writeData(toParent, (const void *)&authRet, sizeof(authRet));
-
- /* ---认证完成\n*/
- _exit(EXIT_SUCCESS);
-}
-
-int main(int argc, char **argv)
-{
- if (argc != 4)
- {
- return EXIT_FAILURE;
- }
- toParent = atoi (argv[1]);
- fromChild = atoi (argv[2]);
- if (toParent == 0 || fromChild == 0)
- {
- printf ("Invalid file descriptors %s %s\n", argv[2], argv[3]);
- return EXIT_FAILURE;
- }
- //mlockall (MCL_CURRENT | MCL_FUTURE);
- fcntl (toParent, F_SETFD, FD_CLOEXEC);
- fcntl (fromChild, F_SETFD, FD_CLOEXEC);
-
-
- _authenticate(argv[3]);
-
-}
diff --git a/checkUserPwdWithPAM/conf/control-center b/checkUserPwdWithPAM/conf/control-center
deleted file mode 100644
index 6af045a..0000000
--- a/checkUserPwdWithPAM/conf/control-center
+++ /dev/null
@@ -1,11 +0,0 @@
-@include common-auth
-auth optional pam_gnome_keyring.so
-
-
-#If you are using Arch,comment out the
-#above and use the following.
-
-#auth include system-auth
-#account include system-auth
-#password include system-auth
-#session include system-auth
diff --git a/checkUserPwdWithPAM/main.cpp b/checkUserPwdWithPAM/main.cpp
new file mode 100644
index 0000000..fd5cc94
--- /dev/null
+++ b/checkUserPwdWithPAM/main.cpp
@@ -0,0 +1,81 @@
+#include <QCoreApplication>
+
+#include <glib.h>
+#include "run-passwd.h"
+
+PasswdHandler *passwd_handler = NULL;
+
+static void auth_cb (PasswdHandler *passwd_handler, GError *error, gpointer user_data);
+static void chpasswd_cb (PasswdHandler *passwd_handler, GError *error, gpointer user_data);
+
+int main(int argc, char *argv[])
+{
+
+ if (argc != 3)
+ {
+ return -1;
+ }
+
+ QCoreApplication a(argc, argv);
+
+ passwd_handler = passwd_init ();
+
+ passwd_authenticate (passwd_handler, argv[1], auth_cb, argv[2]);
+
+ return a.exec();
+}
+
+static void
+auth_cb (PasswdHandler *passwd_handler,
+ GError *error,
+ gpointer user_data)
+{
+ char *secondary_text;
+ char * pwd = (char*) user_data;
+
+ if (error){
+ secondary_text = error->message;
+ printf("%s\n", secondary_text);
+ qApp->exit(1);
+ } else {
+ qApp->exit(1);
+ }
+
+}
+
+/**
+ * @brief chpasswd_cb
+ * @param passwd_handler
+ * @param error
+ * @param user_data
+ */
+static void
+chpasswd_cb (PasswdHandler *passwd_handler,
+ GError *error,
+ gpointer user_data)
+{
+// char *primary_text;
+ char *secondary_text;
+
+ if (!error) {
+ //finish_password_change (TRUE);
+// primary_text = "Success";
+ secondary_text = "";
+
+ printf("%s\n", secondary_text);
+
+ qApp->exit(0);
+ } else {
+// primary_text = "Failed";
+ secondary_text = error->message;
+
+ char ** lines = g_strsplit(secondary_text, "\n", -1);
+
+ printf("%s\n", lines[0]);
+
+ passwd_destroy (passwd_handler);
+
+ qApp->exit(1);
+ }
+
+}
diff --git a/checkUserPwdWithPAM/run-passwd.cpp b/checkUserPwdWithPAM/run-passwd.cpp
new file mode 100644
index 0000000..3b416ec
--- /dev/null
+++ b/checkUserPwdWithPAM/run-passwd.cpp
@@ -0,0 +1,704 @@
+
+
+/* qt会将glib里的signals成员识别为宏所以取消该宏
+ * 后面如果用到signals时使用Q_SIGNALS代替即可
+ **/
+#ifdef signals
+#undef signals
+#endif
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+#include "run-passwd.h"
+
+
+/* Buffer size for backend output */
+#define BUFSIZE 64
+
+/* Passwd states */
+//后端passwd的状态NONE应该是passwd还没有启动ERROR表示报错但还没退出
+typedef enum {
+ PASSWD_STATE_NONE, /* Passwd is not asking for anything */
+ PASSWD_STATE_AUTH, /* Passwd is asking for our current password */
+ PASSWD_STATE_NEW, /* Passwd is asking for our new password */
+ PASSWD_STATE_RETYPE, /* Passwd is asking for our retyped new password */
+ PASSWD_STATE_ERR /* Passwd reported an error but has not yet exited */
+} PasswdState;
+
+struct PasswdHandler {
+// GtkBuilder *ui;
+
+ const char *current_password;
+ const char *new_password;
+ const char *retyped_password;
+
+ /* Communication with the passwd program */
+ GPid backend_pid;
+
+ GIOChannel *backend_stdin;
+ GIOChannel *backend_stdout;
+
+ GQueue *backend_stdin_queue; /* Write queue to backend_stdin */
+
+ /* GMainLoop IDs */
+ guint backend_child_watch_id; /* g_child_watch_add (PID) */
+ guint backend_stdout_watch_id; /* g_io_add_watch (stdout) */
+
+ /* State of the passwd program */
+ PasswdState backend_state;
+ gboolean changing_password;
+
+ PasswdCallback auth_cb;
+ gpointer auth_cb_data;
+
+ PasswdCallback chpasswd_cb;
+ gpointer chpasswd_cb_data;
+};
+
+//GQuark是一个guint32
+static GQuark
+passwd_error_quark (void)
+{
+ static GQuark q = 0;
+
+ //返回错误的标识码
+ if (q == 0) {
+ q = g_quark_from_static_string("passwd_error");
+ }
+
+ return q;
+}
+
+/* Error handling */
+#define PASSWD_ERROR (passwd_error_quark ())
+
+static void stop_passwd (PasswdHandler *passwd_handler);
+
+static void free_passwd_resources (PasswdHandler *passwd_handler);
+
+static gboolean io_watch_stdout (GIOChannel *source, GIOCondition condition, PasswdHandler *passwd_handler);
+
+
+static void free_passwd_resources (PasswdHandler *passwd_handler)
+{
+ GError *error = NULL;
+
+ /* Remove the child watcher */
+ if (passwd_handler->backend_child_watch_id != 0) {
+
+ g_source_remove (passwd_handler->backend_child_watch_id);
+
+ passwd_handler->backend_child_watch_id = 0;
+ }
+
+
+ /* Close IO channels (internal file descriptors are automatically closed) */
+ if (passwd_handler->backend_stdin != NULL) {
+
+ if (g_io_channel_shutdown (passwd_handler->backend_stdin, TRUE, &error) != G_IO_STATUS_NORMAL) {
+ g_warning ("Could not shutdown backend_stdin IO channel: %s", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+
+ g_io_channel_unref (passwd_handler->backend_stdin);
+ passwd_handler->backend_stdin = NULL;
+ }
+
+ if (passwd_handler->backend_stdout != NULL) {
+
+ if (g_io_channel_shutdown (passwd_handler->backend_stdout, TRUE, &error) != G_IO_STATUS_NORMAL) {
+ g_warning ("Could not shutdown backend_stdout IO channel: %s", error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+
+ g_io_channel_unref (passwd_handler->backend_stdout);
+
+ passwd_handler->backend_stdout = NULL;
+ }
+
+ /* Remove IO watcher */
+ if (passwd_handler->backend_stdout_watch_id != 0) {
+
+ g_source_remove (passwd_handler->backend_stdout_watch_id);
+
+ passwd_handler->backend_stdout_watch_id = 0;
+ }
+
+ /* Close PID */
+ //因为flag为G_SPAWN_DO_NOT_REAP_CHILD,所以child不会自动的被reap掉需要在子进程上free
+ if (passwd_handler->backend_pid != -1) {
+
+ g_spawn_close_pid (passwd_handler->backend_pid);
+
+ passwd_handler->backend_pid = -1;
+ }
+
+ /* Clear backend state */
+ passwd_handler->backend_state = PASSWD_STATE_NONE;
+}
+
+static void authenticate (PasswdHandler *passwd_handler)
+{
+ gchar *s;
+
+ s = g_strdup_printf ("%s\n", passwd_handler->current_password);
+ g_queue_push_tail (passwd_handler->backend_stdin_queue, s);
+}
+
+static void io_queue_pop (GQueue *queue, GIOChannel *channel)
+{
+ gchar *buf;
+ gsize bytes_written;
+ GError *error = NULL;
+
+ buf = (gchar *)g_queue_pop_head (queue);
+
+ if (buf != NULL) {
+ //将队列中的首元素写入到channel中
+ if (g_io_channel_write_chars (channel, buf, -1, &bytes_written, &error) != G_IO_STATUS_NORMAL) {
+ g_warning ("Could not write queue element \"%s\" to channel: %s", buf, error->message);
+ g_error_free (error);
+ }
+
+ /* Ensure passwords are cleared from memory */
+ //清除内存中的passwords
+ memset (buf, 0, strlen (buf));
+ g_free (buf);
+ }
+
+}
+
+static gboolean is_string_complete (gchar *str, ...)
+{
+ va_list ap;
+ gchar *arg;
+
+ if (strlen (str) == 0) {
+ return FALSE;
+ }
+
+ va_start (ap, str);
+
+ while ((arg = va_arg (ap, char *)) != NULL) {
+ if (g_strrstr (str, arg) != NULL) {
+ va_end (ap);
+ return TRUE;
+ }
+ }
+
+ va_end (ap);
+
+ return FALSE;
+}
+
+static gboolean io_watch_stdout (GIOChannel *source, GIOCondition condition, PasswdHandler *passwd_handler)
+{
+ static GString *str = NULL; /* Persistent buffer */
+
+ gchar buf[BUFSIZE]; /* Temporary buffer */
+ gsize bytes_read;
+ GError *gio_error = NULL; /* Error returned by functions */
+ GError *error = NULL; /* Error sent to callbacks */
+
+ //GtkBuilder *dialog;
+
+ gboolean reinit = FALSE;
+
+ /* Initialize buffer */
+ if (str == NULL) {
+ str = g_string_new ("");
+ }
+
+ //dialog = passwd_handler->ui;
+ //buf将保存从channel中读取到的数据,bytes_read表示从buf中读取的数据长度
+ if (g_io_channel_read_chars (source, buf, BUFSIZE, &bytes_read, &gio_error)
+ != G_IO_STATUS_NORMAL) {
+ g_warning ("IO Channel read error: %s", gio_error->message);
+ g_error_free (gio_error);
+
+ return TRUE;
+ }
+
+ // g_warning("----------bytes_read=%d",bytes_read);
+ // g_warning("----------io_watch_buf=%s-------",buf);
+
+ str = g_string_append_len (str, buf, bytes_read);
+
+ /* In which state is the backend? */
+ switch (passwd_handler->backend_state) {
+ case PASSWD_STATE_AUTH:
+ /* Passwd is asking for our current password */
+
+ if (is_string_complete (str->str, "assword: ", "failure", "wrong", "error", NULL)) {
+
+ if (g_strrstr (str->str, "New password: ") != NULL) {
+ /* Authentication successful */
+
+ passwd_handler->backend_state = PASSWD_STATE_NEW;
+
+ /* Trigger callback to update authentication status */
+ if (passwd_handler->auth_cb)
+ passwd_handler->auth_cb (passwd_handler,
+ NULL,
+ passwd_handler->auth_cb_data);
+
+ } else {
+ /* Authentication failed */
+
+ error = g_error_new_literal (PASSWD_ERROR, PASSWD_ERROR_AUTH_FAILED,
+ "Authentication token manipulation error!");
+
+ passwd_handler->changing_password = FALSE;
+
+ /* This error can happen both while authenticating or while changing password:
+ * if chpasswd_cb is set, this means we're already changing password */
+ if (passwd_handler->chpasswd_cb)
+ passwd_handler->chpasswd_cb (passwd_handler,
+ error,
+ passwd_handler->auth_cb_data);
+ else if (passwd_handler->auth_cb)
+ passwd_handler->auth_cb (passwd_handler,
+ error,
+ passwd_handler->auth_cb_data);
+
+ g_error_free (error);
+ }
+
+ reinit = TRUE;
+ }
+ break;
+ case PASSWD_STATE_NEW:
+ /* Passwd is asking for our new password */
+
+ if (is_string_complete (str->str, "assword: ", NULL)) {
+ /* Advance to next state */
+ passwd_handler->backend_state = PASSWD_STATE_RETYPE;
+
+ /* Pop retyped password from queue and into IO channel */
+ io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
+
+ reinit = TRUE;
+ }
+ break;
+ case PASSWD_STATE_RETYPE:
+ /* Passwd is asking for our retyped new password */
+
+ // if (is_string_complete (str->str,
+ // "successfully",
+ // "short",
+ // "longer",
+ // "palindrome",
+ // "dictionary",
+ // "simple",
+ // "simplistic",
+ // "similar",
+ // "different",
+ // "case",
+ // "wrapped",
+ // "recovered",
+ // "recent",
+ // "unchanged",
+ // "match",
+ // "1 numeric or special",
+ // "failure",
+ // "length",
+ // NULL)) {
+ if (TRUE){
+
+ if (g_strrstr (str->str, "successfully") != NULL) {
+ /* Hooray! */
+
+ /* Trigger callback to update status */
+ if (passwd_handler->chpasswd_cb)
+ passwd_handler->chpasswd_cb (passwd_handler,
+ NULL,
+ passwd_handler->chpasswd_cb_data);
+ }
+ else {
+ /* Ohnoes! */
+
+ if (g_strrstr (str->str, "recovered") != NULL) {
+ /* What does this indicate?
+ * "Authentication information cannot be recovered?" from libpam? */
+ error = g_error_new_literal (PASSWD_ERROR, PASSWD_ERROR_UNKNOWN,
+ str->str);
+ }/* else if (g_strrstr (str->str, "short") != NULL ||
+ g_strrstr (str->str, "longer") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ "New password length is too short!");
+ } else if (g_strrstr (str->str, "palindrome") != NULL ||
+ g_strrstr (str->str, "simple") != NULL ||
+ g_strrstr (str->str, "simplistic") != NULL ||
+ g_strrstr (str->str, "dictionary") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ "The new password is too simple!");
+ } else if (g_strrstr (str->str, "similar") != NULL ||
+ g_strrstr (str->str, "different") != NULL ||
+ g_strrstr (str->str, "case") != NULL ||
+ g_strrstr (str->str, "wrapped") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ "The new password is too similar to the old one!");
+ } else if (g_strrstr (str->str, "1 numeric or special") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ "The new password must contain numbers or special characters!");
+ } else if (g_strrstr (str->str, "unchanged") != NULL ||
+ g_strrstr (str->str, "match") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ "The new password is the same as the old one!");
+ } else if (g_strrstr (str->str, "recent") != NULL) {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_REJECTED,
+ "The new password has been used recently!");
+ } else if (g_strrstr (str->str, "failure") != NULL) {
+ //Authentication failure
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_AUTH_FAILED,
+ "Your password has been changed after you verify!");
+ } */else {
+ error = g_error_new (PASSWD_ERROR, PASSWD_ERROR_UNKNOWN,
+ "Unknown error");
+ }
+
+ /* At this point, passwd might have exited, in which case
+ * child_watch_cb should clean up for us and remove this watcher.
+ * On some error conditions though, passwd just re-prompts us
+ * for our new password. */
+ passwd_handler->backend_state = PASSWD_STATE_ERR;
+
+ passwd_handler->changing_password = FALSE;
+
+ /* Trigger callback to update status */
+ if (passwd_handler->chpasswd_cb)
+ passwd_handler->chpasswd_cb (passwd_handler,
+ error,
+ passwd_handler->chpasswd_cb_data);
+
+ g_error_free (error);
+
+ }
+
+ reinit = TRUE;
+
+ /* child_watch_cb should clean up for us now */
+ }
+ break;
+ case PASSWD_STATE_NONE:
+ /* Passwd is not asking for anything yet */
+ if (is_string_complete (str->str, "assword: ", NULL)) {
+
+ /* If the user does not have a password set,
+ * passwd will immediately ask for the new password,
+ * so skip the AUTH phase */
+ if (is_string_complete (str->str, "new", "New", NULL)) {
+ gchar *pw;
+
+ passwd_handler->backend_state = PASSWD_STATE_NEW;
+
+ /* since passwd didn't ask for our old password
+ * in this case, simply remove it from the queue */
+ pw = (gchar *)g_queue_pop_head (passwd_handler->backend_stdin_queue);
+ g_free (pw);
+
+ /* Pop the IO queue, i.e. send new password */
+ io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
+ } else {
+
+ passwd_handler->backend_state = PASSWD_STATE_AUTH;
+
+ /* Pop the IO queue, i.e. send current password */
+ io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
+ }
+
+ reinit = TRUE;
+ }
+ break;
+ default:
+ /* Passwd has returned an error */
+ reinit = TRUE;
+ break;
+ }
+
+ if (reinit) {
+ g_string_free (str, TRUE);
+ str = NULL;
+ }
+
+ /* Continue calling us */
+ return TRUE;
+}
+
+/* Child watcher */
+static void child_watch_cb (GPid pid, gint status, PasswdHandler *passwd_handler)
+{
+ //子进程正常结束为非0
+ if (WIFEXITED (status)) {
+ //取得子进程正常退出时返回的结束代码
+ if (WEXITSTATUS (status) >= 255) {
+ g_warning ("Child exited unexpectedly");
+ }
+ }
+
+ free_passwd_resources (passwd_handler);
+}
+
+static void stop_passwd (PasswdHandler *passwd_handler)
+{
+ /* This is the standard way of returning from the dialog with passwd.
+ * If we return this way we can safely kill passwd as it has completed
+ * its task.
+ */
+
+ if (passwd_handler->backend_pid != -1) {
+ kill (passwd_handler->backend_pid, 9);
+ }
+
+ /* We must run free_passwd_resources here and not let our child
+ * watcher do it, since it will access invalid memory after the
+ * dialog has been closed and cleaned up.
+ *
+ * If we had more than a single thread we'd need to remove
+ * the child watch before trying to kill the child.
+ */
+ free_passwd_resources (passwd_handler);
+}
+
+static gboolean spawn_passwd (PasswdHandler *passwd_handler, GError **error)
+{
+ gchar *argv[2];
+ gchar *envp[1];
+ gint my_stdin, my_stdout, my_stderr;
+
+ argv[0] = "/usr/bin/passwd"; /* Is it safe to rely on a hard-coded path? */
+ argv[1] = NULL;
+
+ envp[0] = NULL; /* If we pass an empty array as the environment,
+ * will the childs environment be empty, and the
+ * locales set to the C default? From the manual:
+ * "If envp is NULL, the child inherits its
+ * parent'senvironment."
+ * If I'm wrong here, we somehow have to set
+ * the locales here.
+ */
+
+ //创建一个管道,进行通信,子进程执行passwd命令
+ if (!g_spawn_async_with_pipes (NULL, /* Working directory */
+ argv, /* Argument vector */
+ envp, /* Environment */
+ G_SPAWN_DO_NOT_REAP_CHILD, /* Flags */
+ NULL, /* Child setup 在子进程调用exec()之前,该函数会被调用)*/
+ NULL, /* Data to child setup */
+ &passwd_handler->backend_pid, /* PID */
+ &my_stdin, /* Stdin */
+ &my_stdout, /* Stdout */
+ &my_stderr, /* Stderr */
+ error)) { /* GError */
+
+ /* An error occured */
+ free_passwd_resources (passwd_handler);
+
+ return FALSE;
+ }
+
+ /* 2>&1 */
+ //复制文件描述符也就是将stderr重定向到stdout
+ if (dup2 (my_stderr, my_stdout) == -1) {
+ /* Failed! */
+ g_set_error_literal (error,
+ PASSWD_ERROR,
+ PASSWD_ERROR_BACKEND,
+ strerror (errno));
+
+ /* Clean up */
+ stop_passwd (passwd_handler);
+
+ return FALSE;
+ }
+
+ /* Open IO Channels */
+ //指定一个文件描述符创建一个IO Channel默认使用UTF-8编码格式
+ passwd_handler->backend_stdin = g_io_channel_unix_new (my_stdin);
+ passwd_handler->backend_stdout = g_io_channel_unix_new (my_stdout);
+
+ /* Set raw encoding */
+ /* Set nonblocking mode */
+ //设置通道的编码方式为NULL,设置为非阻塞的方式
+ if (g_io_channel_set_encoding (passwd_handler->backend_stdin, NULL, error) != G_IO_STATUS_NORMAL ||
+ g_io_channel_set_encoding (passwd_handler->backend_stdout, NULL, error) != G_IO_STATUS_NORMAL ||
+ g_io_channel_set_flags (passwd_handler->backend_stdin, G_IO_FLAG_NONBLOCK, error) != G_IO_STATUS_NORMAL ||
+ g_io_channel_set_flags (passwd_handler->backend_stdout, G_IO_FLAG_NONBLOCK, error) != G_IO_STATUS_NORMAL ) {
+
+ /* Clean up */
+ stop_passwd (passwd_handler);
+ return FALSE;
+ }
+
+ /* Turn off buffering */
+ //只有通道的编码方式为NULL才能设置缓冲状态为FASLE其他任何编码通道必须被缓冲这里是为了清掉上次的密码
+ g_io_channel_set_buffered (passwd_handler->backend_stdin, FALSE);
+ g_io_channel_set_buffered (passwd_handler->backend_stdout, FALSE);
+
+ /* Add IO Channel watcher */
+ //当IO通道的状态为G_IO_IN(从IO通道读数据时)或者G_IO_PRI(读紧急数据时)时调用io_watch_stdout
+ passwd_handler->backend_stdout_watch_id = g_io_add_watch (passwd_handler->backend_stdout,
+ G_IO_IN /*| G_IO_PRI*/,
+ (GIOFunc) io_watch_stdout, passwd_handler);
+
+ /* Add child watcher */
+ //在指定pid的进程退出时调用child_watch_cb(),进行错误检查,以及资源回收
+ passwd_handler->backend_child_watch_id = g_child_watch_add (passwd_handler->backend_pid, (GChildWatchFunc) child_watch_cb, passwd_handler);
+
+ /* Success! */
+
+ return TRUE;
+}
+
+static void update_password (PasswdHandler *passwd_handler)
+{
+ gchar *s;
+
+ s = g_strdup_printf ("%s\n", passwd_handler->new_password);
+
+ g_queue_push_tail (passwd_handler->backend_stdin_queue, s);
+ /* We need to allocate new space because io_queue_pop() g_free()s
+ * every element of the queue after it's done */
+ g_queue_push_tail (passwd_handler->backend_stdin_queue, g_strdup (s));
+}
+
+gboolean passwd_change_password (PasswdHandler *passwd_handler,
+ const char *new_password,
+ PasswdCallback cb,
+ const gpointer user_data)
+{
+ GError *error = NULL;
+
+ passwd_handler->changing_password = TRUE;
+
+ passwd_handler->new_password = new_password;
+ passwd_handler->chpasswd_cb = cb;
+ passwd_handler->chpasswd_cb_data = user_data;
+
+ /* Stop passwd if an error occured and it is still running */
+ if (passwd_handler->backend_state == PASSWD_STATE_ERR) {
+
+ /* Stop passwd, free resources */
+ stop_passwd (passwd_handler);
+ }
+
+ /* Check that the backend is still running, or that an error
+ * has occured but it has not yet exited */
+ if (passwd_handler->backend_pid == -1) {
+ /* If it is not, re-run authentication */
+
+ /* Spawn backend */
+ stop_passwd (passwd_handler);
+
+ if (!spawn_passwd (passwd_handler, &error)) {
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ /* Add current and new passwords to queue */
+ //将当前的密码和新密码入队,新密码会入队两次
+ authenticate (passwd_handler);
+ update_password (passwd_handler);
+ } else {
+ /* Only add new passwords to queue */
+ update_password (passwd_handler);
+ }
+
+ /* Pop new password through the backend. If user has no password, popping the queue
+ would output current password, while 'passwd' is waiting for the new one. So wait
+ for io_watch_stdout() to remove current password from the queue, and output
+ the new one for us.*/
+ //如果密码为空将新进队列的密码作为current_passwd弹出
+ if (passwd_handler->current_password)
+ {
+ io_queue_pop (passwd_handler->backend_stdin_queue, passwd_handler->backend_stdin);
+ }
+
+ /* Our IO watcher should now handle the rest */
+
+ return TRUE;
+}
+
+void passwd_authenticate (PasswdHandler *passwd_handler,
+ const char *current_password,
+ PasswdCallback cb,
+ const gpointer user_data)
+{
+ GError *error = NULL;
+
+ /* Don't stop if we've already started chaging password */
+ if (passwd_handler->changing_password)
+ return;
+
+ /* Clear data from possible previous attempts to change password */
+ passwd_handler->new_password = NULL;
+ passwd_handler->chpasswd_cb = NULL;
+ passwd_handler->chpasswd_cb_data = NULL;
+ g_queue_foreach (passwd_handler->backend_stdin_queue, (GFunc) g_free, NULL);
+ g_queue_clear (passwd_handler->backend_stdin_queue);
+
+ passwd_handler->current_password = current_password;
+ passwd_handler->auth_cb = cb;
+ passwd_handler->auth_cb_data = user_data;
+
+ /* Spawn backend */
+ //重新启动后台passwd
+ stop_passwd (passwd_handler);
+
+ if (!spawn_passwd (passwd_handler, &error)) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ //将current passwd从尾部插入队列
+ authenticate (passwd_handler);
+
+ /* Our IO watcher should now handle the rest */
+}
+
+
+PasswdHandler * passwd_init ()
+{
+ PasswdHandler *passwd_handler;
+
+ passwd_handler = g_new0 (PasswdHandler, 1);
+
+ /* Initialize backend_pid. -1 means the backend is not running */
+ //-1代表后台还没启动
+ passwd_handler->backend_pid = -1;
+
+ /* Initialize IO Channels */
+ passwd_handler->backend_stdin = NULL;
+ passwd_handler->backend_stdout = NULL;
+
+ /* Initialize write queue */
+ passwd_handler->backend_stdin_queue = g_queue_new ();
+
+ /* Initialize watchers */
+ passwd_handler->backend_child_watch_id = 0;
+ passwd_handler->backend_stdout_watch_id = 0;
+
+ /* Initialize backend state */
+ passwd_handler->backend_state = PASSWD_STATE_NONE;
+ passwd_handler->changing_password = FALSE;
+
+ return passwd_handler;
+}
+
+
+void passwd_destroy (PasswdHandler *passwd_handler)
+{
+ g_queue_free (passwd_handler->backend_stdin_queue);
+ stop_passwd (passwd_handler);
+ g_free (passwd_handler);
+}
diff --git a/checkUserPwdWithPAM/run-passwd.h b/checkUserPwdWithPAM/run-passwd.h
new file mode 100644
index 0000000..513d05b
--- /dev/null
+++ b/checkUserPwdWithPAM/run-passwd.h
@@ -0,0 +1,34 @@
+#ifndef RUNPASSWD_H
+#define RUNPASSWD_H
+
+
+struct PasswdHandler;
+
+typedef struct PasswdHandler PasswdHandler;
+
+typedef void (*PasswdCallback) (PasswdHandler * passwd_handler, GError * error, const gpointer user_data);
+
+/* Error codes */
+typedef enum {
+ PASSWD_ERROR_REJECTED, /* New password is not secure enough */
+ PASSWD_ERROR_AUTH_FAILED, /* Wrong old password, or PAM failure */
+ PASSWD_ERROR_REAUTH_FAILED, /* Password has changed since first authentication */
+ PASSWD_ERROR_BACKEND, /* Backend error */
+ PASSWD_ERROR_UNKNOWN /* General error */
+} PasswdError;
+
+PasswdHandler *passwd_init ();
+
+void passwd_destroy (PasswdHandler *passwd_handler);
+
+void passwd_authenticate (PasswdHandler *passwd_handler,
+ const char *current_password,
+ PasswdCallback cb,
+ gpointer user_data);
+
+gboolean passwd_change_password (PasswdHandler *passwd_handler,
+ const char *new_password,
+ PasswdCallback cb,
+ const gpointer user_data);
+
+#endif // RUNPASSWD_H
diff --git a/plugins/account/userinfo/changeuserpwd.cpp b/plugins/account/userinfo/changeuserpwd.cpp
index 95f27c9..14acc58 100644
--- a/plugins/account/userinfo/changeuserpwd.cpp
+++ b/plugins/account/userinfo/changeuserpwd.cpp
@@ -402,7 +402,6 @@ void ChangeUserPwd::setupConnect(){
}
char * cmd = g_strdup_printf("/usr/bin/changeuserpwd %s %s", currentPwd.toLatin1().data(), newPwd.toLatin1().data());
-
FILE *stream = NULL;
char buf[256] = {0};
@@ -427,7 +426,7 @@ void ChangeUserPwd::setupConnect(){
}
} else {
- if (re.contains("Failed")){
+ if (re.contains("Authentication token manipulation error!")){
curPwdTip = tr("Authentication failed, input authtok again!");
}
diff --git a/plugins/account/userinfo/pwdcheckthread.cpp b/plugins/account/userinfo/pwdcheckthread.cpp
index 37e9af6..2fbb0e9 100644
--- a/plugins/account/userinfo/pwdcheckthread.cpp
+++ b/plugins/account/userinfo/pwdcheckthread.cpp
@@ -37,7 +37,7 @@ void PwdCheckThread::run(){
}
}
- snprintf(command, 128, "/usr/bin/checkUserPwd %s %s", ba1.data(), currentPwd.toLatin1().data());
+ snprintf(command, 128, "/usr/bin/checkUserPwd %s %s", currentPwd.toLatin1().data(), ba1.data());
if ((stream = popen(command, "r")) != NULL){
diff --git a/translate_generation.sh b/translate_generation.sh
index c971497..bfb9c88 100755
--- a/translate_generation.sh
+++ b/translate_generation.sh
@@ -7,7 +7,7 @@ version=(`echo $ID`)
for ts in "${ts_list[@]}"
do
printf "\nprocess ${ts}\n"
- if [ "$version" == "fedora" ] || [ "$version" == "opensuse-leap" ] || [ "$version" == "opensuse-tumbleweed" ] || [ "$version" == "openEuler" ];then
+ if [ "$version" == "fedora" ] || [ "$version" == "opensuse-leap" ] || [ "$version" == "opensuse-tumbleweed" ] || [ "$version" == "openEuler" ] || [ "$version" == "kylin" ];then
lrelease-qt5 "${ts}"
else
lrelease "${ts}"
--
2.36.1