1895 lines
61 KiB
Diff
1895 lines
61 KiB
Diff
|
|
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
|
|||
|
|
|