/******************************************************************************* * Copyright (c) 2013, 2014 Lectorius, Inc. * Authors: * Vijay Pandurangan (vijayp@mitro.co) * Evan Jones (ej@mitro.co) * Adam Hilss (ahilss@mitro.co) * * * 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 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, see <http://www.gnu.org/licenses/>. * * You can contact the authors at inbound@mitro.co. *******************************************************************************/ package co.mitro.core.servlets; import static org.hamcrest.CoreMatchers.containsString; import static org.junit.Assert.*; import java.sql.SQLException; import java.util.Iterator; import org.junit.Before; import org.junit.Test; import co.mitro.core.crypto.KeyInterfaces.CryptoError; import co.mitro.core.crypto.KeyInterfaces.PrivateKeyInterface; import co.mitro.core.server.data.DBGroup; import co.mitro.core.server.data.DBGroupSecret; import co.mitro.core.server.data.DBIdentity; import co.mitro.core.server.data.DBServerVisibleSecret; import co.mitro.core.server.data.RPC.UpdateSecretFromAgentRequest; import co.mitro.core.server.data.RPC.UpdateSecretFromAgentRequest.UserData; import co.mitro.core.server.data.RPC.UpdateSecretFromAgentRequest.UserData.CriticalData; import co.mitro.core.servlets.MitroServlet.MitroRequestContext; public class UpdateSecretFromAgentTest extends OrganizationsFixture { private UserData userdata; private UpdateSecretFromAgent servlet; @SuppressWarnings("unused") private DBGroup testGroup2; @SuppressWarnings("unused") private DBGroup testGroup3; private DBServerVisibleSecret svs; private DBIdentity thirdParty = null; private DBIdentity randomAdmin; private UpdateSecretFromAgentRequest request; private PrivateKeyInterface randomAdminKey; private PrivateKeyInterface thirdPartyKey; private static final String OLD = "old"; private static final String NEW = "new"; @Before public void setUp() throws Exception { svs = this.createSecret(testGroup, "client", "critical", org); userdata = new UserData(); userdata.secretId = svs.getId(); userdata.criticalData = new CriticalData(); userdata.criticalData.oldPassword = OLD; userdata.criticalData.password = NEW; userdata.criticalData.note = null; request = new UpdateSecretFromAgentRequest(); servlet = new UpdateSecretFromAgent(managerFactory, keyFactory); Iterator<DBIdentity> iterator = outsiders.iterator(); testGroup2 = this.createGroupContainingIdentity(testIdentity2); thirdParty = iterator.next(); testGroup3 = this.createGroupContainingIdentity(thirdParty); Iterator<DBIdentity> adminIter = admins.iterator(); while (adminIter.hasNext()){ randomAdmin = adminIter.next(); if (randomAdmin.getId() != testIdentity.getId()) { break; } else { randomAdmin = null; } } randomAdminKey = keyFactory.generate(); randomAdmin.setPublicKeyString(randomAdminKey.exportPublicKey().toString()); manager.identityDao.update(randomAdmin); thirdPartyKey = keyFactory.generate(); thirdParty.setPublicKeyString(thirdPartyKey.exportPublicKey().toString()); manager.identityDao.update(thirdParty); } private void process(DBIdentity requestor) throws Exception { servlet.processCommand( new MitroRequestContext(requestor, gson.toJson(request), manager, null)); } private void expectFailure(DBIdentity requestor, String msg) { try { process(requestor); fail("expected exception"); } catch (Throwable t) { if (null != msg) { assertThat(t.getMessage(), containsString(msg)); } } } @Test public void editSecretDataOK() throws Exception { userdata.userId = randomAdmin.getName(); fillRequestWithSignature(randomAdminKey); process(null); verifyCriticalData(); } @Test public void editSecretDataOKWithRequestor() throws Exception { userdata.userId = randomAdmin.getName(); fillRequestWithSignature(randomAdminKey); process(testIdentity); //TODO: this is fragile verifyCriticalData(); } @Test public void editSecretDataWithBadSignature() throws Exception { userdata.userId = randomAdmin.getName(); fillRequestWithSignature(thirdPartyKey); expectFailure(null, "did not sign"); expectFailure(testIdentity, "did not sign"); } @Test public void editSecretDataWithUserWithNoAccess() throws Exception { userdata.userId = thirdParty.getName(); fillRequestWithSignature(thirdPartyKey); expectFailure(null, "does not have access"); expectFailure(testIdentity, "does not have access"); } @Test public void editSecretDataWithBadDomainUser() throws Exception { DBIdentity exampleOrgIdentity = createIdentity("user2@example.org", null); PrivateKeyInterface exampleOrgIdentityKey = keyFactory.generate(); exampleOrgIdentity.setPublicKeyString(exampleOrgIdentityKey.exportPublicKey().toString()); DBGroup domain2Group = createGroupContainingIdentity(exampleOrgIdentity); addSecretToGroup(svs, domain2Group, "client", "critical"); userdata.userId = exampleOrgIdentity.getName(); fillRequestWithSignature(exampleOrgIdentityKey); expectFailure(null, "permitted domains list"); expectFailure(testIdentity, "permitted domains list"); } private void verifyCriticalData() throws SQLException, CryptoError { // get the server visible secret DBServerVisibleSecret svs = manager.svsDao.queryForId(userdata.secretId); for (DBGroupSecret gs : svs.getGroupSecrets()) { PrivateKeyInterface key = groupToPrivateKeyMap.get(gs.getGroup().getId()); CriticalData actual = gson.fromJson(key.decrypt(gs.getCriticalDataEncrypted()), CriticalData.class); assertEquals(actual, userdata.criticalData); assertEquals(actual.password, NEW); // TODO: fix memorydbfixture to actually encrypt these data assertEquals(gs.getClientVisibleDataEncrypted(), "client"); } } private void fillRequestWithSignature(PrivateKeyInterface key) throws CryptoError { request.dataFromUserSignature = null; request.dataFromUser = gson.toJson(userdata); if (null != key) { request.dataFromUserSignature = key.sign(request.dataFromUser); } } }