/****************************************************************************** * * * Copyright 2017 Subterranean Security * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * *****************************************************************************/ package com.subterranean_security.crimson.server.store; import java.util.ArrayList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.subterranean_security.crimson.core.attribute.keys.AKeySimple; import com.subterranean_security.crimson.core.misc.AuthenticationGroup; import com.subterranean_security.crimson.core.misc.MemList; import com.subterranean_security.crimson.core.net.Connector; import com.subterranean_security.crimson.core.proto.Delta.EV_ServerProfileDelta; import com.subterranean_security.crimson.core.proto.Delta.EV_ViewerProfileDelta; import com.subterranean_security.crimson.core.proto.MSG.Message; import com.subterranean_security.crimson.core.proto.Misc.AuthMethod; import com.subterranean_security.crimson.core.proto.Misc.AuthType; import com.subterranean_security.crimson.core.proto.Misc.Outcome; import com.subterranean_security.crimson.core.store.ConnectionStore; import com.subterranean_security.crimson.core.util.CryptoUtil; import com.subterranean_security.crimson.server.net.ServerConnectionStore; import com.subterranean_security.crimson.sv.permissions.Perm; import com.subterranean_security.crimson.sv.permissions.ViewerPermissions; import com.subterranean_security.crimson.sv.profile.ClientProfile; import com.subterranean_security.crimson.sv.profile.ViewerProfile; import com.subterranean_security.crimson.universal.Universal; import com.subterranean_security.crimson.universal.stores.DatabaseStore; public class Authentication { private Authentication() { } private static final Logger log = LoggerFactory.getLogger(Authentication.class); private static MemList<AuthMethod> methods = null; static { try { methods = (MemList<AuthMethod>) DatabaseStore.getDatabase().getObject("auth.methods"); methods.setDatabase(DatabaseStore.getDatabase()); } catch (Exception e) { e.printStackTrace(); } } public static AuthMethod getGroupMethod(String groupname) { for (int i = 0; i < methods.size(); i++) { AuthMethod m = methods.get(i); if (m.getName().equals(groupname)) { return m; } } return null; } public static AuthenticationGroup getGroup(String name) { try { return (AuthenticationGroup) DatabaseStore.getDatabase().getObject(getGroupMethod(name).getGroup()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public static Outcome create(AuthMethod am) { Outcome.Builder outcome = Outcome.newBuilder(); remove(am.getId()); if (am.getType() == AuthType.GROUP) { am = AuthMethod.newBuilder().mergeFrom(am).setGroup(DatabaseStore.getDatabase() .store(CryptoUtil.generateGroup(am.getName(), am.getGroupSeedPrefix().getBytes()))).build(); } methods.add(am); // update viewers ServerConnectionStore.sendToAll(Universal.Instance.VIEWER, Message.newBuilder() .setEvServerProfileDelta(EV_ServerProfileDelta.newBuilder().addAuthMethod(am)).build()); return outcome.setResult(true).build(); } public static void remove(int id) { for (int i = 0; i < methods.size(); i++) { if (methods.get(i).getId() == id) { methods.remove(i); return; } } } public static AuthMethod getPassword(String s) { for (int i = 0; i < methods.size(); i++) { if (s.equals(methods.get(i).getPassword())) { return methods.get(i); } } return null; } public static void refreshAllVisibilityPermissions() { for (Integer i : ProfileStore.getClientKeyset()) { refreshVisibilityPermissions(i); } } public static void refreshVisibilityPermissions(int cid) { ClientProfile cp = ProfileStore.getClient(cid); if (cp == null) { log.warn("Could not refresh permissions for nonexistant client: {}", cid); return; } AuthMethod clientAuth = null; for (int i = 0; i < methods.size(); i++) { AuthMethod am = methods.get(i); if (cp.getAuthID() == am.getId()) { clientAuth = am; break; } } ArrayList<Integer> changed = new ArrayList<Integer>(); if (clientAuth == null) { // no auth; append all viewers for (Integer i : ProfileStore.getViewerKeyset()) { ViewerProfile vp = ProfileStore.getViewer(i); log.debug("Adding visibility flag to viewer {} for client {}", vp.getCvid(), cid); vp.getPermissions().addFlag(cid, Perm.client.visibility); // TODO only send if changed changed.add(vp.getCvid()); } } else { for (Integer i : ProfileStore.getViewerKeyset()) { ViewerProfile vp = ProfileStore.getViewer(i); if (clientAuth.getOwnerList().contains(vp.get(AKeySimple.VIEWER_USER)) || clientAuth.getMemberList().contains(vp.get(AKeySimple.VIEWER_USER))) { // this viewer has authority over this client log.debug("Adding visibility flag to viewer {} for client {}", vp.getCvid(), cid); vp.getPermissions().addFlag(cid, Perm.client.visibility); // TODO only send if changed changed.add(vp.getCvid()); } } } for (int id : changed) { Connector r = ConnectionStore.get(id); if (r != null) { r.write(Message.newBuilder() .setEvViewerProfileDelta(EV_ViewerProfileDelta.newBuilder() .addViewerPermissions(ViewerPermissions.translateFlag(cid, Perm.client.visibility))) .build()); } } } }