/******************************************************************************* * 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 java.io.IOException; import java.sql.SQLException; import java.util.Collections; import javax.servlet.annotation.WebServlet; import co.mitro.core.accesscontrol.AuthenticatedDB; import co.mitro.core.exceptions.InvalidRequestException; import co.mitro.core.exceptions.MitroServletException; import co.mitro.core.exceptions.PermissionException; import co.mitro.core.server.Manager; import co.mitro.core.server.data.DBAcl; import co.mitro.core.server.data.DBAudit; import co.mitro.core.server.data.DBGroup; import co.mitro.core.server.data.DBGroupSecret; import co.mitro.core.server.data.DBGroupSecret.CRITICAL; import co.mitro.core.server.data.DBIdentity; import co.mitro.core.server.data.RPC; import co.mitro.core.server.data.RPC.GetGroupResponse; import co.mitro.core.server.data.RPC.MitroRPC; import com.google.common.collect.Lists; @WebServlet("/api/GetGroup") public class GetGroup extends MitroServlet { private static final long serialVersionUID = 1L; @Override protected MitroRPC processCommand(MitroRequestContext context) throws IOException, SQLException, MitroServletException { RPC.GetGroupRequest in = gson.fromJson(context.jsonRequest, RPC.GetGroupRequest.class); final DBGroup group = context.manager.groupDao.queryForId(in.groupId); // TODO: Remove this once the client code no longer sends this id @SuppressWarnings("deprecation") String deprecatedId = in.userId; throwIfRequestorDoesNotEqualUserId(context.requestor, deprecatedId); @SuppressWarnings("deprecation") AuthenticatedDB userDb = AuthenticatedDB.deprecatedNew(context.manager, context.requestor); // check if requestor is a member of group (has full access) boolean hasFullAccess = false; if (null != userDb.getGroupAsUserOrOrgAdmin(group.getId())) { hasFullAccess = true; } else { // throws if we don't have access try { DBGroup result = userDb.getGroupForAddSecret(group.getId()); assert result.getId() == group.getId(); } catch (MitroServletException e) { // preserve behavior by throwing PermissionException if (e.getMessage().startsWith("User should not be able to see group")) { throw new PermissionException("user does not have permission to access group"); } } } RPC.GetGroupResponse out = new RPC.GetGroupResponse(); fillEditGroupRequest(context.manager, group, out, null); out.secrets = Lists.newArrayList(); if (!hasFullAccess) { // don't reveal encrypted group keys to a limited access requestor out.acls = Collections.emptyList(); } else if (null != group.getGroupSecrets()) { assert hasFullAccess; for (DBGroupSecret gs : group.getGroupSecrets()) { RPC.Secret secret = new RPC.Secret(); gs.addToRpcSecret(context.manager, secret, in.includeCriticalData ? CRITICAL.INCLUDE_CRITICAL_DATA : CRITICAL.NO_CRITICAL_DATA, context.requestor.getName()); out.secrets.add(secret); } } return out; } protected static void fillEditGroupRequest(Manager mgr, final DBGroup group, RPC.EditGroupRequest out, String deviceId) throws SQLException, MitroServletException { out.groupId = group.getId(); out.name = group.getName(); out.scope = group.getScope(); out.autoDelete = group.isAutoDelete(); out.publicKey = group.getPublicKeyString(); out.signatureString = group.getSignatureString(); out.acls = Lists.newArrayList(); assert out.name != null; mgr.addAuditLog(DBAudit.ACTION.GET_GROUP, null, null, group, null, null); for (DBAcl acl : group.getAcls()) { GetGroupResponse.ACL out_acl = new GetGroupResponse.ACL(); // TODO: Don't return groupKeyEncrypted if it isn't actually for the user! out_acl.groupKeyEncryptedForMe = acl.getGroupKeyEncryptedForMe(); assert out_acl.groupKeyEncryptedForMe != null; out_acl.level = acl.getLevel(); if (null != acl.getMemberGroupId()) { DBGroup memberGroup = acl.loadMemberGroup(mgr.groupDao); out_acl.myPublicKey = memberGroup.getPublicKeyString(); out_acl.memberGroup = memberGroup.getId(); } else if (null != acl.getMemberIdentityId()) { DBIdentity memberIdentity = acl.loadMemberIdentity(mgr.identityDao); out_acl.myPublicKey = memberIdentity.getPublicKeyString(); out_acl.memberIdentity = memberIdentity.getName(); } else { throw new InvalidRequestException("Invalid ACL: both memberGroup and memberIdentity are null"); } out.acls.add(out_acl); } } }