Merge lp:~mardy/signon/rtm-fixes into lp:~online-accounts/signon/rtm-14.09

Proposed by Alberto Mardegan
Status: Approved
Approved by: David Barth
Approved revision: 623
Proposed branch: lp:~mardy/signon/rtm-fixes
Merge into: lp:~online-accounts/signon/rtm-14.09
Diff against target: 909 lines (+506/-196)
17 files modified
debian/changelog (+6/-0)
lib/plugins/SignOn/uisessiondata_priv.h (+2/-0)
src/signond/accesscontrolmanagerhelper.cpp (+1/-1)
src/signond/signondaemonadaptor.cpp (+1/-1)
src/signond/signonidentity.cpp (+8/-30)
src/signond/signonidentityinfo.cpp (+12/-0)
src/signond/signonidentityinfo.h (+2/-0)
src/signond/signonsessioncore.cpp (+6/-2)
tests/libsignon-qt-tests/ssotestclient.cpp (+127/-161)
tests/libsignon-qt-tests/ssotestclient.h (+1/-1)
tests/libsignon-qt-tests/testauthsession.cpp (+1/-0)
tests/signond-tests/.gitignore (+1/-0)
tests/signond-tests/signond-tests.pri (+2/-0)
tests/signond-tests/signond-tests.pro (+1/-0)
tests/signond-tests/timeouts.cpp (+2/-0)
tests/signond-tests/tst_access_control_manager_helper.cpp (+320/-0)
tests/signond-tests/tst_access_control_manager_helper.pro (+13/-0)
To merge this branch: bzr merge lp:~mardy/signon/rtm-fixes
Reviewer Review Type Date Requested Status
David Barth (community) Approve
Review via email: mp+243137@code.launchpad.net

Commit message

Don't bypass the ACL if the identity has no owner

This includes some fixes and refactoring to the unit tests.

Description of the change

Don't bypass the ACL if the identity has no owner

This includes some fixes and refactoring to the unit tests.

To post a comment you must log in.
Revision history for this message
David Barth (dbarth) :
review: Approve
lp:~mardy/signon/rtm-fixes updated
623. By Alberto Mardegan

Fix changelog

Revision history for this message
David Barth (dbarth) :
review: Approve

Unmerged revisions

623. By Alberto Mardegan

Fix changelog

622. By Alberto Mardegan

Don't bypass the ACL if the identity has no owner

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/changelog'
2--- debian/changelog 2014-10-06 07:57:10 +0000
3+++ debian/changelog 2014-11-28 12:00:40 +0000
4@@ -1,3 +1,9 @@
5+signon (8.57+14.10.20141006-0ubuntu2) UNRELEASED; urgency=medium
6+
7+ * Don't bypass the ACL if the identity has no owner. (LP: #1392380)
8+
9+ -- Alberto Mardegan <alberto.mardegan@canonical.com> Fri, 28 Nov 2014 13:54:25 +0200
10+
11 signon (8.57+14.10.20141006-0ubuntu1) utopic; urgency=low
12
13 [ Alberto Mardegan ]
14
15=== modified file 'lib/plugins/SignOn/uisessiondata_priv.h'
16--- lib/plugins/SignOn/uisessiondata_priv.h 2014-10-02 13:57:24 +0000
17+++ lib/plugins/SignOn/uisessiondata_priv.h 2014-11-28 12:00:40 +0000
18@@ -68,6 +68,8 @@
19
20 /* Process ID of the client application */
21 #define SSOUI_KEY_PID QLatin1String("Pid")
22+/* Application ID (security context) of the client application */
23+#define SSOUI_KEY_APP_ID QLatin1String("AppId")
24
25 #define SSOUI_KEY_SLOT_ACCEPT "accept"
26 #define SSOUI_KEY_SLOT_REJECT "reject"
27
28=== modified file 'src/signond/accesscontrolmanagerhelper.cpp'
29--- src/signond/accesscontrolmanagerhelper.cpp 2013-08-20 08:01:44 +0000
30+++ src/signond/accesscontrolmanagerhelper.cpp 2014-11-28 12:00:40 +0000
31@@ -89,7 +89,7 @@
32
33 IdentityOwnership ownership =
34 isPeerOwnerOfIdentity(peerConnection, peerMessage, identityId);
35- if (ownership == ApplicationIsOwner || ownership == IdentityDoesNotHaveOwner)
36+ if (ownership == ApplicationIsOwner)
37 return true;
38
39 if (acl.isEmpty())
40
41=== modified file 'src/signond/signondaemonadaptor.cpp'
42--- src/signond/signondaemonadaptor.cpp 2013-08-20 08:01:44 +0000
43+++ src/signond/signondaemonadaptor.cpp 2014-11-28 12:00:40 +0000
44@@ -172,7 +172,7 @@
45
46 /* Access Control */
47 if (id != SIGNOND_NEW_IDENTITY) {
48- if (!acm->isPeerAllowedToUseAuthSession(conn, msg, id)) {
49+ if (!acm->isPeerAllowedToUseIdentity(conn, msg, id)) {
50 SignOn::AccessReply *reply =
51 acm->requestAccessToIdentity(conn, msg, id);
52 /* If the request is accepted, we'll need the method name ("type")
53
54=== modified file 'src/signond/signonidentity.cpp'
55--- src/signond/signonidentity.cpp 2014-08-21 07:33:45 +0000
56+++ src/signond/signonidentity.cpp 2014-11-28 12:00:40 +0000
57@@ -471,41 +471,19 @@
58 MethodMap methods = container.isValid() ?
59 qdbus_cast<MethodMap>(container.value<QDBusArgument>()) : MethodMap();
60
61- //Add creator to owner list if it has AID
62- QStringList ownerList =
63- info.value(SIGNOND_IDENTITY_INFO_OWNER).toStringList();
64- if (!appId.isNull())
65- ownerList.append(appId);
66-
67 if (m_pInfo == 0) {
68 m_pInfo = new SignonIdentityInfo(info);
69 m_pInfo->setMethods(methods);
70+ //Add creator to owner list if it has AID
71+ QStringList ownerList =
72+ info.value(SIGNOND_IDENTITY_INFO_OWNER).toStringList();
73+ if (!appId.isNull()) {
74+ ownerList.append(appId);
75+ }
76 m_pInfo->setOwnerList(ownerList);
77 } else {
78- if (info.contains(SIGNOND_IDENTITY_INFO_SECRET)) {
79- QString secret = info.value(SIGNOND_IDENTITY_INFO_SECRET).toString();
80- m_pInfo->setPassword(secret);
81- }
82- bool storeSecret =
83- info.value(SIGNOND_IDENTITY_INFO_STORESECRET).toBool();
84- QString userName =
85- info.value(SIGNOND_IDENTITY_INFO_USERNAME).toString();
86- QString caption =
87- info.value(SIGNOND_IDENTITY_INFO_CAPTION).toString();
88- QStringList realms =
89- info.value(SIGNOND_IDENTITY_INFO_REALMS).toStringList();
90- QStringList accessControlList =
91- info.value(SIGNOND_IDENTITY_INFO_ACL).toStringList();
92- int type = info.value(SIGNOND_IDENTITY_INFO_TYPE).toInt();
93-
94- m_pInfo->setStorePassword(storeSecret);
95- m_pInfo->setUserName(userName);
96- m_pInfo->setCaption(caption);
97- m_pInfo->setMethods(methods);
98- m_pInfo->setRealms(realms);
99- m_pInfo->setAccessControlList(accessControlList);
100- m_pInfo->setOwnerList(ownerList);
101- m_pInfo->setType(type);
102+ SignonIdentityInfo newInfo(info);
103+ m_pInfo->update(newInfo);
104 }
105
106 m_id = storeCredentials(*m_pInfo);
107
108=== modified file 'src/signond/signonidentityinfo.cpp'
109--- src/signond/signonidentityinfo.cpp 2013-11-26 14:23:18 +0000
110+++ src/signond/signonidentityinfo.cpp 2014-11-28 12:00:40 +0000
111@@ -60,6 +60,18 @@
112 return *this;
113 }
114
115+void SignonIdentityInfo::update(const SignonIdentityInfo &info)
116+{
117+ QMapIterator<QString, QVariant> it(info);
118+ while (it.hasNext()) {
119+ it.next();
120+ // We don't allow updating the ID
121+ if (it.key() == SIGNOND_IDENTITY_INFO_ID) continue;
122+
123+ insert(it.key(), it.value());
124+ }
125+}
126+
127 bool SignonIdentityInfo::checkMethodAndMechanism(const QString &method,
128 const QString &mechanism,
129 QString &allowedMechanism)
130
131=== modified file 'src/signond/signonidentityinfo.h'
132--- src/signond/signonidentityinfo.h 2013-11-26 14:23:18 +0000
133+++ src/signond/signonidentityinfo.h 2014-11-28 12:00:40 +0000
134@@ -46,6 +46,8 @@
135
136 const QVariantMap toMap() const;
137
138+ void update(const SignonIdentityInfo &info);
139+
140 void setNew() { setId(SIGNOND_NEW_IDENTITY); }
141 bool isNew() const { return id() == SIGNOND_NEW_IDENTITY; }
142 void setId(quint32 id) { insert(SIGNOND_IDENTITY_INFO_ID, id); }
143
144=== modified file 'src/signond/signonsessioncore.cpp'
145--- src/signond/signonsessioncore.cpp 2014-10-02 13:57:24 +0000
146+++ src/signond/signonsessioncore.cpp 2014-11-28 12:00:40 +0000
147@@ -705,8 +705,12 @@
148 request.m_params[SSOUI_KEY_CLIENT_DATA] = m_clientData;
149 request.m_params[SSOUI_KEY_METHOD] = m_method;
150 request.m_params[SSOUI_KEY_MECHANISM] = request.m_mechanism;
151- request.m_params[SSOUI_KEY_PID] =
152- AccessControlManagerHelper::instance()->pidOfPeer(request.m_conn,
153+ /* Pass some data about the requesting client */
154+ AccessControlManagerHelper *acm =
155+ AccessControlManagerHelper::instance();
156+ request.m_params[SSOUI_KEY_PID] = acm->pidOfPeer(request.m_conn,
157+ request.m_msg);
158+ request.m_params[SSOUI_KEY_APP_ID] = acm->appIdOfPeer(request.m_conn,
159 request.m_msg);
160
161 CredentialsAccessManager *camManager =
162
163=== modified file 'tests/libsignon-qt-tests/ssotestclient.cpp'
164--- tests/libsignon-qt-tests/ssotestclient.cpp 2013-11-22 14:46:01 +0000
165+++ tests/libsignon-qt-tests/ssotestclient.cpp 2014-11-28 12:00:40 +0000
166@@ -257,16 +257,137 @@
167 TEST_DONE
168 }
169
170+void SsoTestClient::storeCredentials_data()
171+{
172+ QTest::addColumn<bool>("addMethods");
173+
174+ QTest::newRow("with methods") << true;
175+ QTest::newRow("without methods") << false;
176+}
177+
178 void SsoTestClient::storeCredentials()
179 {
180 TEST_START
181
182- if (!testAddingNewCredentials()) {
183- QFAIL("Adding new credentials test failed.");
184- }
185-
186- if (!testUpdatingCredentials()) {
187- QFAIL("Updating existing credentials test failed.");
188+ QFETCH(bool, addMethods);
189+
190+ m_identityResult.reset();
191+
192+ QMap<MethodName, MechanismsList> methods;
193+ if (addMethods) {
194+ methods.insert("dummy", QStringList() << "mech1" << "mech2" << "mech3");
195+ methods.insert("dummy1", QStringList() << "mech11" << "mech12" << "mech13");
196+ }
197+ IdentityInfo info("TEST_CAPTION", "TEST_USERNAME", methods);
198+ info.setSecret("TEST_SECRET");
199+ info.setRealms(QStringList() << "TEST_REALM1" << "TEST_REALM2");
200+ info.setAccessControlList(QStringList() << "*");
201+
202+ Identity *identity = Identity::newIdentity(info, this);
203+
204+ QEventLoop loop;
205+
206+ connect(identity, SIGNAL(error(const SignOn::Error &)),
207+ &m_identityResult, SLOT(error(const SignOn::Error &)));
208+
209+ connect(identity, SIGNAL(credentialsStored(const quint32)),
210+ &m_identityResult, SLOT(credentialsStored(const quint32)));
211+ connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit()));
212+
213+ identity->storeCredentials();
214+
215+ QTimer::singleShot(test_timeout, &loop, SLOT(quit()));
216+ loop.exec();
217+
218+ if (m_identityResult.m_responseReceived ==
219+ TestIdentityResult::InexistentResp) {
220+ QFAIL("A response was not received.");
221+ }
222+
223+ if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) {
224+ QCOMPARE(m_identityResult.m_id, identity->id());
225+
226+ Identity *existingIdentity =
227+ Identity::existingIdentity(m_identityResult.m_id, this);
228+ QVERIFY2(existingIdentity != NULL,
229+ "Could not create existing identity. '0' ID provided?");
230+ connect(existingIdentity, SIGNAL(info(const SignOn::IdentityInfo &)),
231+ &m_identityResult, SLOT(info(const SignOn::IdentityInfo &)));
232+
233+ existingIdentity->queryInfo();
234+
235+ QTimer::singleShot(test_timeout, &loop, SLOT(quit()));
236+ loop.exec();
237+ delete existingIdentity;
238+
239+ if (!TestIdentityResult::compareIdentityInfos(m_identityResult.m_idInfo,
240+ info)) {
241+ QFAIL("Compared identity infos are not the same.");
242+ }
243+ } else {
244+ QString codeStr = errCodeAsStr(m_identityResult.m_error);
245+ qDebug() << "Error reply: " << m_serviceResult.m_errMsg
246+ << ".\nError code: " << codeStr;
247+ QFAIL("Error received");
248+ }
249+
250+ // Test update credentials functionality
251+
252+ Identity *existingIdentity = Identity::existingIdentity(m_identityResult.m_id, this);
253+ QVERIFY2(existingIdentity != NULL,
254+ "Could not create existing identity. '0' ID provided?");
255+
256+ methods.clear();
257+ if (addMethods) {
258+ methods.insert("dummy1", QStringList() << "mech11" << "mech12" << "mech13");
259+ methods.insert("dummy2", QStringList() << "mech1_updated" << "mech2" << "mech1_updated2");
260+ methods.insert("dummy3", QStringList() << "mech1_updated" << "mech2" << "mech1_updated2");
261+ }
262+
263+ IdentityInfo updateInfo("TEST_CAPTION", "TEST_USERNAME_UPDATED", methods);
264+ updateInfo.setSecret("TEST_SECRET_YES", false);
265+
266+ do
267+ {
268+ QEventLoop loop;
269+
270+ connect(existingIdentity, SIGNAL(error(const SignOn::Error &)),
271+ &m_identityResult, SLOT(error(const SignOn::Error &)));
272+
273+ connect(existingIdentity, SIGNAL(credentialsStored(const quint32)),
274+ &m_identityResult, SLOT(credentialsStored(const quint32)));
275+ connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit()));
276+
277+ existingIdentity->storeCredentials(updateInfo);
278+ qDebug();
279+ QTimer::singleShot(test_timeout, &loop, SLOT(quit()));
280+ loop.exec();
281+ } while(0);
282+
283+ if (m_identityResult.m_responseReceived ==
284+ TestIdentityResult::InexistentResp) {
285+ QFAIL("A response was not received.");
286+ }
287+
288+ if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) {
289+ QEventLoop loop;
290+ connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit()));
291+ connect(existingIdentity, SIGNAL(info(const SignOn::IdentityInfo &)),
292+ &m_identityResult, SLOT(info(const SignOn::IdentityInfo &)));
293+
294+ existingIdentity->queryInfo();
295+ QTimer::singleShot(test_timeout, &loop, SLOT(quit()));
296+ loop.exec();
297+
298+ qDebug() << "ID:" << existingIdentity->id();
299+ QCOMPARE(m_identityResult.m_idInfo.caption(), updateInfo.caption());
300+ QCOMPARE(m_identityResult.m_idInfo.methods(), updateInfo.methods());
301+ QCOMPARE(m_identityResult.m_idInfo.userName(), updateInfo.userName());
302+ } else {
303+ QString codeStr = errCodeAsStr(m_identityResult.m_error);
304+ qDebug() << "Error reply: " << m_serviceResult.m_errMsg
305+ << ".\nError code: " << codeStr;
306+ QFAIL("Error received");
307 }
308
309 TEST_DONE
310@@ -566,21 +687,6 @@
311 TEST_DONE
312 }
313
314-void SsoTestClient::storeCredentialsWithoutAuthMethodsTest()
315-{
316- TEST_START
317-
318- if (!testAddingNewCredentials(false)) {
319- QFAIL("Adding new credentials test failed.");
320- }
321-
322- if (!testUpdatingCredentials()) {
323- QFAIL("Updating existing credentials test failed.");
324- }
325-
326- TEST_DONE
327-}
328-
329 void SsoTestClient::queryInfo()
330 {
331 TEST_START
332@@ -1448,146 +1554,6 @@
333 TEST_DONE
334 }
335
336-bool SsoTestClient::testAddingNewCredentials(bool addMethods)
337-{
338- m_identityResult.reset();
339-
340- QMap<MethodName, MechanismsList> methods;
341- if (addMethods) {
342- methods.insert("dummy", QStringList() << "mech1" << "mech2" << "mech3");
343- methods.insert("dummy1", QStringList() << "mech11" << "mech12" << "mech13");
344- }
345- IdentityInfo info("TEST_CAPTION", "TEST_USERNAME", methods);
346- info.setSecret("TEST_SECRET");
347- info.setRealms(QStringList() << "TEST_REALM1" << "TEST_REALM2");
348-
349- Identity *identity = Identity::newIdentity(info, this);
350-
351- QEventLoop loop;
352-
353- connect(identity, SIGNAL(error(const SignOn::Error &)),
354- &m_identityResult, SLOT(error(const SignOn::Error &)));
355-
356- connect(identity, SIGNAL(credentialsStored(const quint32)),
357- &m_identityResult, SLOT(credentialsStored(const quint32)));
358- connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit()));
359-
360- identity->storeCredentials();
361-
362- QTimer::singleShot(test_timeout, &loop, SLOT(quit()));
363- loop.exec();
364-
365- if (m_identityResult.m_responseReceived ==
366- TestIdentityResult::InexistentResp) {
367- qDebug() << "A response was not received.";
368- return false;
369- }
370-
371- if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) {
372- if (m_identityResult.m_id != identity->id()) {
373- qDebug() << "Queried identity id does not match with stored data.";
374- return false;
375- }
376-
377- Identity *existingIdentity =
378- Identity::existingIdentity(m_identityResult.m_id, this);
379- if (existingIdentity == NULL) {
380- qDebug() << "Could not create existing identity. '0' ID provided?";
381- return false;
382- }
383- connect(existingIdentity, SIGNAL(info(const SignOn::IdentityInfo &)),
384- &m_identityResult, SLOT(info(const SignOn::IdentityInfo &)));
385-
386- existingIdentity->queryInfo();
387-
388- QTimer::singleShot(test_timeout, &loop, SLOT(quit()));
389- loop.exec();
390- delete existingIdentity;
391-
392- if (!TestIdentityResult::compareIdentityInfos(m_identityResult.m_idInfo,
393- info)) {
394- qDebug() << "Compared identity infos are not the same.";
395- return false;
396- }
397- } else {
398- QString codeStr = errCodeAsStr(m_identityResult.m_error);
399- qDebug() << "Error reply: " << m_serviceResult.m_errMsg
400- << ".\nError code: " << codeStr;
401- return false;
402- }
403- return true;
404-}
405-
406-bool SsoTestClient::testUpdatingCredentials(bool addMethods)
407-{
408- // Test update credentials functionality
409-
410- Identity *existingIdentity = Identity::existingIdentity(m_identityResult.m_id, this);
411- if (existingIdentity == NULL) {
412- qDebug() << "Could not create existing identity. '0' ID provided?";
413- return false;
414- }
415-
416- QMap<MethodName, MechanismsList> methods;
417- if (addMethods) {
418- methods.insert("dummy1", QStringList() << "mech11" << "mech12" << "mech13");
419- methods.insert("dummy2", QStringList() << "mech1_updated" << "mech2" << "mech1_updated2");
420- methods.insert("dummy3", QStringList() << "mech1_updated" << "mech2" << "mech1_updated2");
421- }
422-
423- IdentityInfo updateInfo("TEST_CAPTION", "TEST_USERNAME_UPDATED", methods);
424- updateInfo.setSecret("TEST_SECRET_YES", false);
425-
426- do
427- {
428- QEventLoop loop;
429-
430- connect(existingIdentity, SIGNAL(error(const SignOn::Error &)),
431- &m_identityResult, SLOT(error(const SignOn::Error &)));
432-
433- connect(existingIdentity, SIGNAL(credentialsStored(const quint32)),
434- &m_identityResult, SLOT(credentialsStored(const quint32)));
435- connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit()));
436-
437- existingIdentity->storeCredentials(updateInfo);
438- qDebug();
439- QTimer::singleShot(test_timeout, &loop, SLOT(quit()));
440- loop.exec();
441- } while(0);
442-
443- qDebug();
444- if (m_identityResult.m_responseReceived ==
445- TestIdentityResult::InexistentResp) {
446- qDebug() << "A response was not received.";
447- return false;
448- }
449-
450- if (m_identityResult.m_responseReceived == TestIdentityResult::NormalResp) {
451- QEventLoop loop;
452- connect(&m_identityResult, SIGNAL(testCompleted()), &loop, SLOT(quit()));
453- connect(existingIdentity, SIGNAL(info(const SignOn::IdentityInfo &)),
454- &m_identityResult, SLOT(info(const SignOn::IdentityInfo &)));
455-
456- existingIdentity->queryInfo();
457- QTimer::singleShot(test_timeout, &loop, SLOT(quit()));
458- loop.exec();
459-
460- qDebug() << "ID:" << existingIdentity->id();
461- if (!TestIdentityResult::compareIdentityInfos(m_identityResult.m_idInfo,
462- updateInfo)) {
463- qDebug() << "Compared identity infos are not the same.";
464- return false;
465- }
466- } else {
467- QString codeStr = errCodeAsStr(m_identityResult.m_error);
468- qDebug() << "Error reply: " << m_serviceResult.m_errMsg
469- << ".\nError code: " << codeStr;
470-
471- return false;
472- }
473- return true;
474-}
475-
476 void SsoTestClient::emptyPasswordRegression()
477 {
478 TEST_START
479
480=== modified file 'tests/libsignon-qt-tests/ssotestclient.h'
481--- tests/libsignon-qt-tests/ssotestclient.h 2013-11-22 14:46:01 +0000
482+++ tests/libsignon-qt-tests/ssotestclient.h 2014-11-28 12:00:40 +0000
483@@ -56,6 +56,7 @@
484 * Identity tests
485 */
486 void queryAvailableMetods();
487+ void storeCredentials_data();
488 void storeCredentials();
489 void requestCredentialsUpdate();
490 void queryInfo();
491@@ -65,7 +66,6 @@
492 void verifySecret();
493 void signOut();
494 void remove();
495- void storeCredentialsWithoutAuthMethodsTest();
496 void sessionTest();
497 void multipleRemove();
498 void removeStoreRemove();
499
500=== modified file 'tests/libsignon-qt-tests/testauthsession.cpp'
501--- tests/libsignon-qt-tests/testauthsession.cpp 2013-11-12 09:09:04 +0000
502+++ tests/libsignon-qt-tests/testauthsession.cpp 2014-11-28 12:00:40 +0000
503@@ -361,6 +361,7 @@
504 methods.insert(QLatin1String("ssotest"), mechs);
505 IdentityInfo info("test_caption", "test_user_name", methods);
506 info.setSecret("test_secret");
507+ info.setAccessControlList(QStringList() << "*");
508 Identity *id = Identity::newIdentity(info, this);
509
510 QSignalSpy spyResponseStoreCreds(id, SIGNAL(credentialsStored(const quint32)));
511
512=== modified file 'tests/signond-tests/.gitignore'
513--- tests/signond-tests/.gitignore 2013-08-20 08:01:44 +0000
514+++ tests/signond-tests/.gitignore 2014-11-28 12:00:40 +0000
515@@ -1,6 +1,7 @@
516 /identity-tool
517 /mock-ac-plugin/identity-ac-helper
518 /tst_access_control
519+/tst_access_control_manager_helper
520 /tst_backup
521 /tst_database
522 /tst_pluginproxy
523
524=== modified file 'tests/signond-tests/signond-tests.pri'
525--- tests/signond-tests/signond-tests.pri 2013-08-20 08:01:43 +0000
526+++ tests/signond-tests/signond-tests.pri 2014-11-28 12:00:40 +0000
527@@ -23,6 +23,8 @@
528 $${TOP_BUILD_DIR}/lib/signond/SignOn
529 QMAKE_RPATHDIR = $${QMAKE_LIBDIR}
530
531+SIGNOND_SRC = $${TOP_SRC_DIR}/src/signond
532+
533 DEFINES += SIGNOND_TRACE
534 DEFINES += SIGNON_PLUGIN_TRACE
535
536
537=== modified file 'tests/signond-tests/signond-tests.pro'
538--- tests/signond-tests/signond-tests.pro 2013-08-20 08:01:44 +0000
539+++ tests/signond-tests/signond-tests.pro 2014-11-28 12:00:40 +0000
540@@ -1,5 +1,6 @@
541 TEMPLATE = subdirs
542 SUBDIRS = \
543+ tst_access_control_manager_helper.pro \
544 tst_timeouts.pro \
545 tst_pluginproxy.pro \
546 tst_database.pro \
547
548=== modified file 'tests/signond-tests/timeouts.cpp'
549--- tests/signond-tests/timeouts.cpp 2013-08-20 08:01:43 +0000
550+++ tests/signond-tests/timeouts.cpp 2014-11-28 12:00:40 +0000
551@@ -62,6 +62,7 @@
552 IdentityInfo info = IdentityInfo(QLatin1String("timeout test"),
553 QLatin1String("timeout@test"),
554 methods);
555+ info.setAccessControlList(QStringList() << "*");
556 Identity *identity = Identity::newIdentity(info);
557 QVERIFY(identity != NULL);
558
559@@ -135,6 +136,7 @@
560 IdentityInfo info = IdentityInfo(QLatin1String("timeout test"),
561 QLatin1String("timeout@test"),
562 methods);
563+ info.setAccessControlList(QStringList() << "*");
564 Identity *identity = Identity::newIdentity(info);
565 QVERIFY(identity != NULL);
566
567
568=== added file 'tests/signond-tests/tst_access_control_manager_helper.cpp'
569--- tests/signond-tests/tst_access_control_manager_helper.cpp 1970-01-01 00:00:00 +0000
570+++ tests/signond-tests/tst_access_control_manager_helper.cpp 2014-11-28 12:00:40 +0000
571@@ -0,0 +1,320 @@
572+/*
573+ * This file is part of signon
574+ *
575+ * Copyright (C) 2014 Canonical Ltd.
576+ *
577+ * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
578+ *
579+ * This library is free software; you can redistribute it and/or
580+ * modify it under the terms of the GNU Lesser General Public License
581+ * version 2.1 as published by the Free Software Foundation.
582+ *
583+ * This library is distributed in the hope that it will be useful, but
584+ * WITHOUT ANY WARRANTY; without even the implied warranty of
585+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
586+ * Lesser General Public License for more details.
587+ *
588+ * You should have received a copy of the GNU Lesser General Public
589+ * License along with this library; if not, write to the Free Software
590+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
591+ * 02110-1301 USA
592+ */
593+
594+#include <QByteArray>
595+#include <QDBusConnection>
596+#include <QDBusMessage>
597+#include <QDebug>
598+#include <QSignalSpy>
599+#include <QTest>
600+
601+#include <SignOn/AbstractAccessControlManager>
602+#include "accesscontrolmanagerhelper.h"
603+#include "credentialsaccessmanager.h"
604+#include "credentialsdb.h"
605+
606+using namespace SignOn;
607+using namespace SignonDaemonNS;
608+
609+// mock AbstractAccessControlManager {
610+class AcmPlugin: public SignOn::AbstractAccessControlManager
611+{
612+ Q_OBJECT
613+
614+public:
615+ AcmPlugin(QObject *parent = 0):
616+ SignOn::AbstractAccessControlManager(parent) {}
617+ ~AcmPlugin() {}
618+
619+ bool isPeerAllowedToAccess(const QDBusConnection &peerConnection,
620+ const QDBusMessage &peerMessage,
621+ const QString &securityContext) {
622+ QStringList appPermissions =
623+ m_permissions.value(appIdOfPeer(peerConnection, peerMessage));
624+ return appPermissions.contains(securityContext);
625+ }
626+
627+ QString appIdOfPeer(const QDBusConnection &peerConnection,
628+ const QDBusMessage &peerMessage) {
629+ Q_UNUSED(peerConnection);
630+ return peerMessage.service();
631+ }
632+
633+ QString keychainWidgetAppId() { return m_keychainWidgetAppId; }
634+
635+ SignOn::AccessReply *handleRequest(const SignOn::AccessRequest &request) {
636+ Q_UNUSED(request);
637+ return 0;
638+ }
639+
640+private:
641+ friend class AccessControlManagerHelperTest;
642+ QMap<QString,QStringList> m_permissions;
643+ QString m_keychainWidgetAppId;
644+};
645+// } mock AbstractAccessControlManager
646+
647+class AccessControlManagerHelperTest: public QObject
648+{
649+ Q_OBJECT
650+
651+public:
652+ AccessControlManagerHelperTest();
653+
654+private Q_SLOTS:
655+ void init();
656+ void testOwnership_data();
657+ void testOwnership();
658+ void testIdentityAccess_data();
659+ void testIdentityAccess();
660+
661+public:
662+ static AccessControlManagerHelperTest *instance() { return m_instance; }
663+ SignonDaemonNS::CredentialsDB *credentialsDB() { return &m_db; }
664+
665+private:
666+ void setDbOwners(const QStringList &owners) {
667+ if (owners.contains("db-error")) {
668+ m_dbOwners = QStringList();
669+ m_dbLastError = CredentialsDBError("DB error!",
670+ CredentialsDBError::ConnectionError);
671+ } else {
672+ m_dbOwners = owners;
673+ }
674+ }
675+
676+ void setDbAcl(const QStringList &acl) {
677+ if (acl.contains("db-error")) {
678+ m_dbAcl = QStringList();
679+ m_dbLastError = CredentialsDBError("DB error!",
680+ CredentialsDBError::ConnectionError);
681+ } else {
682+ m_dbAcl = acl;
683+ }
684+ }
685+
686+private:
687+ friend class SignonDaemonNS::CredentialsDB;
688+ static AccessControlManagerHelperTest *m_instance;
689+ AcmPlugin m_acmPlugin;
690+ SignonDaemonNS::CredentialsDB m_db;
691+ SignOn::CredentialsDBError m_dbLastError;
692+ QStringList m_dbAcl;
693+ QStringList m_dbOwners;
694+ QDBusConnection m_conn;
695+};
696+
697+AccessControlManagerHelperTest *AccessControlManagerHelperTest::m_instance = 0;
698+
699+namespace SignonDaemonNS {
700+// mock CredentialsDB {
701+CredentialsDB::CredentialsDB(const QString &metaDataDbName,
702+ SignOn::AbstractSecretsStorage *secretsStorage):
703+ QObject()
704+{
705+ Q_UNUSED(metaDataDbName);
706+ Q_UNUSED(secretsStorage);
707+}
708+
709+CredentialsDB::~CredentialsDB()
710+{
711+}
712+
713+SignOn::CredentialsDBError CredentialsDB::lastError() const
714+{
715+ return AccessControlManagerHelperTest::instance()->m_dbLastError;
716+}
717+
718+QStringList CredentialsDB::accessControlList(const quint32 identityId)
719+{
720+ Q_UNUSED(identityId);
721+ return AccessControlManagerHelperTest::instance()->m_dbAcl;
722+}
723+
724+QStringList CredentialsDB::ownerList(const quint32 identityId)
725+{
726+ Q_UNUSED(identityId);
727+ return AccessControlManagerHelperTest::instance()->m_dbOwners;
728+}
729+// } mock CredentialsDB
730+
731+// mock CredentialsAccessManager {
732+CredentialsDB *CredentialsAccessManager::credentialsDB() const {
733+ return AccessControlManagerHelperTest::instance()->credentialsDB();
734+}
735+CredentialsAccessManager *CredentialsAccessManager::instance() {
736+ return 0;
737+}
738+} // namespace
739+// } mock CredentialsAccessManager
740+
741+AccessControlManagerHelperTest::AccessControlManagerHelperTest():
742+ QObject(),
743+ m_db(QString(), 0),
744+ m_conn(QLatin1String("test-connection"))
745+{
746+ m_instance = this;
747+}
748+
749+void AccessControlManagerHelperTest::init()
750+{
751+ m_dbOwners = QStringList();
752+ m_dbAcl = QStringList();
753+ m_dbLastError = CredentialsDBError();
754+}
755+
756+void AccessControlManagerHelperTest::testOwnership_data()
757+{
758+ QTest::addColumn<QString>("peer");
759+ QTest::addColumn<QStringList>("ownerList");
760+ QTest::addColumn<int>("expectedOwnership");
761+
762+ QTest::newRow("DB error") <<
763+ "tom" <<
764+ (QStringList() << "db-error") <<
765+ int(AccessControlManagerHelper::ApplicationIsNotOwner);
766+
767+ QTest::newRow("empty") <<
768+ "tom" <<
769+ QStringList() <<
770+ int(AccessControlManagerHelper::IdentityDoesNotHaveOwner);
771+
772+ QTest::newRow("is only owner") <<
773+ "tom" <<
774+ (QStringList() << "tom") <<
775+ int(AccessControlManagerHelper::ApplicationIsOwner);
776+
777+ QTest::newRow("is co-owner") <<
778+ "tom" <<
779+ (QStringList() << "Bob" << "tom" << "harry") <<
780+ int(AccessControlManagerHelper::ApplicationIsOwner);
781+}
782+
783+void AccessControlManagerHelperTest::testOwnership()
784+{
785+ QFETCH(QString, peer);
786+ QFETCH(QStringList, ownerList);
787+ QFETCH(int, expectedOwnership);
788+
789+ setDbOwners(ownerList);
790+
791+ m_acmPlugin.m_permissions["tom"] = QStringList() << "tom" << "Tom";
792+
793+ /* forge a QDBusMessage */
794+ QDBusMessage msg =
795+ QDBusMessage::createMethodCall(peer, "/", "interface", "hi");
796+
797+ SignonDaemonNS::AccessControlManagerHelper helper(&m_acmPlugin);
798+
799+ AccessControlManagerHelper::IdentityOwnership ownership =
800+ helper.isPeerOwnerOfIdentity(m_conn, msg, 3);
801+
802+ QCOMPARE(int(ownership), expectedOwnership);
803+}
804+
805+void AccessControlManagerHelperTest::testIdentityAccess_data()
806+{
807+ QTest::addColumn<QString>("peer");
808+ QTest::addColumn<QStringList>("ownerList");
809+ QTest::addColumn<QStringList>("acl");
810+ QTest::addColumn<bool>("expectedIsAllowed");
811+
812+ QTest::newRow("DB error") <<
813+ "tom" <<
814+ (QStringList() << "tom") <<
815+ (QStringList() << "db-error") <<
816+ false;
817+
818+ QTest::newRow("is owner, ACL empty") <<
819+ "tom" <<
820+ (QStringList() << "tom") <<
821+ QStringList() <<
822+ true;
823+
824+ QTest::newRow("is owner, not in ACL") <<
825+ "tom" <<
826+ (QStringList() << "tom") <<
827+ (QStringList() << "bob") <<
828+ true;
829+
830+ QTest::newRow("is owner, in ACL") <<
831+ "tom" <<
832+ (QStringList() << "tom") <<
833+ (QStringList() << "bob" << "tom" << "harry") <<
834+ true;
835+
836+ QTest::newRow("is owner, ACL=*") <<
837+ "tom" <<
838+ (QStringList() << "tom") <<
839+ (QStringList() << "*") <<
840+ true;
841+
842+ QTest::newRow("not owner, ACL empty") <<
843+ "tom" <<
844+ (QStringList() << "bob") <<
845+ QStringList() <<
846+ false;
847+
848+ QTest::newRow("not owner, not in ACL") <<
849+ "tom" <<
850+ (QStringList() << "bob") <<
851+ (QStringList() << "bob") <<
852+ false;
853+
854+ QTest::newRow("not owner, in ACL") <<
855+ "tom" <<
856+ (QStringList() << "bob") <<
857+ (QStringList() << "bob" << "tom" << "harry") <<
858+ true;
859+
860+ QTest::newRow("not owner, ACL=*") <<
861+ "tom" <<
862+ (QStringList() << "bob") <<
863+ (QStringList() << "*") <<
864+ true;
865+}
866+
867+void AccessControlManagerHelperTest::testIdentityAccess()
868+{
869+ QFETCH(QString, peer);
870+ QFETCH(QStringList, ownerList);
871+ QFETCH(QStringList, acl);
872+ QFETCH(bool, expectedIsAllowed);
873+
874+ setDbOwners(ownerList);
875+ setDbAcl(acl);
876+
877+ m_acmPlugin.m_permissions["tom"] = QStringList() << "tom" << "Tom";
878+
879+ /* forge a QDBusMessage */
880+ QDBusMessage msg =
881+ QDBusMessage::createMethodCall(peer, "/", "interface", "hi");
882+
883+ SignonDaemonNS::AccessControlManagerHelper helper(&m_acmPlugin);
884+
885+ bool isAllowed = helper.isPeerAllowedToUseIdentity(m_conn, msg, 3);
886+
887+ QCOMPARE(isAllowed, expectedIsAllowed);
888+}
889+
890+QTEST_MAIN(AccessControlManagerHelperTest)
891+#include "tst_access_control_manager_helper.moc"
892
893=== added file 'tests/signond-tests/tst_access_control_manager_helper.pro'
894--- tests/signond-tests/tst_access_control_manager_helper.pro 1970-01-01 00:00:00 +0000
895+++ tests/signond-tests/tst_access_control_manager_helper.pro 2014-11-28 12:00:40 +0000
896@@ -0,0 +1,13 @@
897+TARGET = tst_access_control_manager_helper
898+
899+include(signond-tests.pri)
900+
901+SOURCES = \
902+ $${SIGNOND_SRC}/accesscontrolmanagerhelper.cpp \
903+ tst_access_control_manager_helper.cpp
904+
905+HEADERS = \
906+ $${SIGNOND_SRC}/accesscontrolmanagerhelper.h \
907+ $${SIGNOND_SRC}/credentialsdb.h
908+
909+check.commands = "./$$TARGET"

Subscribers

People subscribed via source and target branches