on xenial help sign in
Allow logging into a desktop or tablet session again, by properly dismissing old PAM conversations. (LP: #1350878)
f35c4e8Michael Terry
qml/Greeter/GreeterContent.qml−1
@@ -87,7 +87,6 @@ Item {
87
87
88 onLoaded: {
88 onLoaded: {
89 item.currentIndex = greeterContentLoader.currentIndex;
89 item.currentIndex = greeterContentLoader.currentIndex;
90− item.resetAuthentication();
91 }
90 }
92
91
93 Binding {
92 Binding {
tests/mocks/LightDM/demo/GreeterPrivate.cpp+42−13
@@ -33,6 +33,12 @@ class GreeterImpl : public QObject
33{
33{
34 Q_OBJECT
34 Q_OBJECT
35
35
36+ struct AppData
37+ {
38+ GreeterImpl *impl;
39+ pam_handle *handle;
40+ };
41+
36 typedef QFutureInterface<QString> ResponseFuture;
42 typedef QFutureInterface<QString> ResponseFuture;
37
43
38public:
44public:
@@ -46,11 +52,11 @@ public:
46
52
47 connect(&futureWatcher, SIGNAL(finished()),
53 connect(&futureWatcher, SIGNAL(finished()),
48 this, SLOT(finishPam()));
54 this, SLOT(finishPam()));
49− connect(this, SIGNAL(showMessage(QString, QLightDM::Greeter::MessageType)),
55+ connect(this, SIGNAL(showMessage(pam_handle *, QString, QLightDM::Greeter::MessageType)),
50− greeter, SIGNAL(showMessage(QString, QLightDM::Greeter::MessageType)));
56+ this, SLOT(handleMessage(pam_handle *, QString, QLightDM::Greeter::MessageType)));
51 // This next connect is how we pass ResponseFutures between threads
57 // This next connect is how we pass ResponseFutures between threads
52− connect(this, SIGNAL(showPrompt(QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)),
58+ connect(this, SIGNAL(showPrompt(pam_handle *, QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)),
53− this, SLOT(handlePrompt(QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)));
59+ this, SLOT(handlePrompt(pam_handle *, QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)));
54 }
60 }
55
61
56 void start(QString username)
62 void start(QString username)
@@ -64,14 +70,19 @@ public:
64 pam_end(handle, PAM_CONV_ERR);
70 pam_end(handle, PAM_CONV_ERR);
65 }
71 }
66
72
73+ AppData *appData = new AppData();
74+ appData->impl = this;
75+
67 // Now actually start a new conversation with PAM
76 // Now actually start a new conversation with PAM
68 pam_conv conversation;
77 pam_conv conversation;
69 conversation.conv = converseWithPam;
78 conversation.conv = converseWithPam;
70− conversation.appdata_ptr = static_cast<void*>(this);
79+ conversation.appdata_ptr = static_cast<void*>(appData);
71
80
72 if (pam_start("lightdm", username.toUtf8(), &conversation, &pamHandle) == PAM_SUCCESS) {
81 if (pam_start("lightdm", username.toUtf8(), &conversation, &pamHandle) == PAM_SUCCESS) {
82+ appData->handle = pamHandle;
73 futureWatcher.setFuture(QtConcurrent::run(authenticateWithPam, pamHandle));
83 futureWatcher.setFuture(QtConcurrent::run(authenticateWithPam, pamHandle));
74 } else {
84 } else {
85+ delete appData;
75 greeterPrivate->authenticated = false;
86 greeterPrivate->authenticated = false;
76 Q_EMIT greeter->showMessage("Internal error: could not start PAM authentication", QLightDM::Greeter::MessageTypeError);
87 Q_EMIT greeter->showMessage("Internal error: could not start PAM authentication", QLightDM::Greeter::MessageTypeError);
77 Q_EMIT greeter->authenticationComplete();
88 Q_EMIT greeter->authenticationComplete();
@@ -103,7 +114,9 @@ public:
103 if (!tmp_response)
114 if (!tmp_response)
104 return PAM_CONV_ERR;
115 return PAM_CONV_ERR;
105
116
106− GreeterImpl* impl = static_cast<GreeterImpl*>(appdata_ptr);
117+ AppData *appData = static_cast<AppData*>(appdata_ptr);
118+ GreeterImpl *impl = appData->impl;
119+ pam_handle *handle = appData->handle;
107
120
108 int count;
121 int count;
109 QVector<ResponseFuture> responses;
122 QVector<ResponseFuture> responses;
@@ -117,7 +130,7 @@ public:
117 QString message(msg[count]->msg);
130 QString message(msg[count]->msg);
118 responses.append(ResponseFuture());
131 responses.append(ResponseFuture());
119 responses.last().reportStarted();
132 responses.last().reportStarted();
120− Q_EMIT impl->showPrompt(message, Greeter::PromptTypeQuestion, responses.last());
133+ Q_EMIT impl->showPrompt(handle, message, Greeter::PromptTypeQuestion, responses.last());
121 break;
134 break;
122 }
135 }
123 case PAM_PROMPT_ECHO_OFF:
136 case PAM_PROMPT_ECHO_OFF:
@@ -125,19 +138,19 @@ public:
125 QString message(msg[count]->msg);
138 QString message(msg[count]->msg);
126 responses.append(ResponseFuture());
139 responses.append(ResponseFuture());
127 responses.last().reportStarted();
140 responses.last().reportStarted();
128− Q_EMIT impl->showPrompt(message, Greeter::PromptTypeSecret, responses.last());
141+ Q_EMIT impl->showPrompt(handle, message, Greeter::PromptTypeSecret, responses.last());
129 break;
142 break;
130 }
143 }
131 case PAM_TEXT_INFO:
144 case PAM_TEXT_INFO:
132 {
145 {
133 QString message(msg[count]->msg);
146 QString message(msg[count]->msg);
134− Q_EMIT impl->showMessage(message, Greeter::MessageTypeInfo);
147+ Q_EMIT impl->showMessage(handle, message, Greeter::MessageTypeInfo);
135 break;
148 break;
136 }
149 }
137 default:
150 default:
138 {
151 {
139 QString message(msg[count]->msg);
152 QString message(msg[count]->msg);
140− Q_EMIT impl->showMessage(message, Greeter::MessageTypeError);
153+ Q_EMIT impl->showMessage(handle, message, Greeter::MessageTypeError);
141 break;
154 break;
142 }
155 }
143 }
156 }
@@ -159,6 +172,8 @@ public:
159 }
172 }
160 }
173 }
161
174
175+ delete appData;
176+
162 if (raise_error)
177 if (raise_error)
163 {
178 {
164 for (int i = 0; i < count; ++i)
179 for (int i = 0; i < count; ++i)
@@ -186,8 +201,8 @@ public Q_SLOTS:
186 }
201 }
187
202
188Q_SIGNALS:
203Q_SIGNALS:
189− void showMessage(QString text, QLightDM::Greeter::MessageType type);
204+ void showMessage(pam_handle *handle, QString text, QLightDM::Greeter::MessageType type);
190− void showPrompt(QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture response);
205+ void showPrompt(pam_handle *handle, QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture response);
191
206
192private Q_SLOTS:
207private Q_SLOTS:
193 void finishPam()
208 void finishPam()
@@ -205,8 +220,22 @@ private Q_SLOTS:
205 Q_EMIT greeter->authenticationComplete();
220 Q_EMIT greeter->authenticationComplete();
206 }
221 }
207
222
223+ void handleMessage(pam_handle *handle, QString text, QLightDM::Greeter::MessageType type)
224+ {
225+ if (handle != pamHandle)
226+ return;
227+
228+ Q_EMIT greeter->showMessage(text, type);
229+ }
230+
208− void handlePrompt(QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture future)
231+ void handlePrompt(pam_handle *handle, QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture future)
209 {
232 {
233+ if (handle != pamHandle) {
234+ future.reportResult(QString());
235+ future.reportFinished();
236+ return;
237+ }
238+
210 futures.enqueue(future);
239 futures.enqueue(future);
211 Q_EMIT greeter->showPrompt(text, type);
240 Q_EMIT greeter->showPrompt(text, type);
212 }
241 }