/** * Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2016 * * 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 org.glite.security.voms.admin.operations; import java.security.cert.X509Certificate; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.glite.security.voms.admin.operations.util.CurrentAdminPermissionCache; import org.glite.security.voms.admin.persistence.dao.VOMSAdminDAO; import org.glite.security.voms.admin.persistence.dao.VOMSRoleDAO; import org.glite.security.voms.admin.persistence.dao.VOMSUserDAO; import org.glite.security.voms.admin.persistence.model.ACL; import org.glite.security.voms.admin.persistence.model.Certificate; import org.glite.security.voms.admin.persistence.model.VOMSAdmin; import org.glite.security.voms.admin.persistence.model.VOMSCA; import org.glite.security.voms.admin.persistence.model.VOMSGroup; import org.glite.security.voms.admin.persistence.model.VOMSRole; import org.glite.security.voms.admin.persistence.model.VOMSUser; import org.glite.security.voms.admin.util.DNUtil; import org.italiangrid.utils.voms.CurrentSecurityContext; import org.italiangrid.utils.voms.SecurityContext; import org.italiangrid.voms.VOMSAttribute; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CurrentAdmin { private static final Logger log = LoggerFactory.getLogger(CurrentAdmin.class); private static ThreadLocal<CurrentAdmin> currentAdmin = new ThreadLocal<>(); private VOMSAdmin admin; public VOMSAdmin getAdmin() { return admin; } protected CurrentAdmin(VOMSAdmin a) { this.admin = a; } private static VOMSAdmin lookupAdmin() { SecurityContext ctxt = (SecurityContext) CurrentSecurityContext.get(); VOMSAdmin admin = VOMSAdminDAO.instance() .lookup(ctxt.getClientName(), ctxt.getIssuerName()); return admin; } public static CurrentAdmin instance() { if (currentAdmin.get() != null) { return currentAdmin.get(); } VOMSAdmin admin = lookupAdmin(); if (admin == null) { admin = VOMSAdminDAO.instance() .getAnyAuthenticatedUserAdmin(); } currentAdmin.set(new CurrentAdmin(admin)); return currentAdmin.get(); } public static void clear() { currentAdmin.set(null); } public VOMSCA getCa() { return admin.getCa(); } public String getDn() { return admin.getDn(); } public boolean isAuthorizedAdmin() { return !getAdmin().equals(VOMSAdminDAO.instance() .getAnyAuthenticatedUserAdmin()); } public boolean isVoUser() { return (getVoUser() != null); } public boolean is(VOMSUser u) { if (getVoUser() == null) return false; return getVoUser().equals(u); } public boolean is(Certificate c) { return getRealSubject().equals(c.getSubjectString()) && getRealIssuer().equals(c.getCa() .getSubjectString()); } public boolean hasLinkedUser() { return (getVoUser() != null); } public VOMSUser getVoUser() { String lookupSubject, lookupIssuer; if (!isAuthorizedAdmin()) { lookupSubject = getRealSubject(); lookupIssuer = getRealIssuer(); } else { lookupSubject = admin.getDn(); lookupIssuer = admin.getCa() .getSubjectString(); } VOMSUser user = VOMSUserDAO.instance() .lookup(lookupSubject, lookupIssuer); return user; } public void createVoUser() { VOMSUser usr = getVoUser(); if (usr == null) { VOMSUserDAO.instance() .create(getRealSubject(), getRealIssuer(), getRealCN(), null, getRealEmailAddress()); } } public boolean isVOAdmin() { if (hasPermissions(VOMSContext.getVoContext(), VOMSPermission.getAllPermissions())) return true; if (hasPermissions(VOMSContext.getVoContext(), VOMSPermission.getRequestsRWPermissions())) return true; return false; } public boolean canBrowseVO() { return hasPermissions(VOMSContext.getVoContext(), VOMSPermission.getContainerReadPermission() .setMembershipReadPermission()); } public boolean checkPermission(VOMSContext c, VOMSPermission p) { ACL acl = c.getACL(); if (log.isDebugEnabled()) { log.debug("Checking if admin {} has permission {} in context {}", new Object[] { getAdmin(), p, c }); log.debug("ACL for this context: "); log.debug(acl.toString()); } if (isUnauthenticated()) { VOMSPermission unauthPerms = acl.getUnauthenticatedClientPermissions(); if (unauthPerms == null) return false; return unauthPerms.satisfies(p); } VOMSUser adminVOUser = getVoUser(); if (log.isDebugEnabled()) { log.debug("Admin VO user: {}", adminVOUser); } VOMSPermission personalPermissions = acl.getPermissions(admin); if (log.isDebugEnabled()) { log.debug("Personal permissions for admin: {}", personalPermissions); } VOMSPermission anyAuthenticatedUserPermissions = acl .getAnyAuthenticatedUserPermissions(); if (log.isDebugEnabled()) { log.debug("Permissions for any authenticated user: {}", anyAuthenticatedUserPermissions); } int effectivePerms = 0; VOMSPermission unauthenticatedClientPermissions = acl .getUnauthenticatedClientPermissions(); if (log.isDebugEnabled()) { log.debug("Permissions for unauthenticated clients: {}", unauthenticatedClientPermissions); } if (personalPermissions == null && adminVOUser == null && anyAuthenticatedUserPermissions == null && unauthenticatedClientPermissions == null) return false; if (personalPermissions != null) { effectivePerms = effectivePerms | personalPermissions.getBits(); } if (anyAuthenticatedUserPermissions != null) { effectivePerms = effectivePerms | anyAuthenticatedUserPermissions.getBits(); } if (unauthenticatedClientPermissions != null) { effectivePerms = effectivePerms | unauthenticatedClientPermissions.getBits(); } if (adminVOUser == null) { VOMSPermission adminEffectivePerms = VOMSPermission .fromBits(effectivePerms); log.debug("Admin effective permissions {}", adminEffectivePerms); boolean result = adminEffectivePerms.satisfies(p); if (log.isDebugEnabled()) { log.debug("Does {} have permissions that satisfy {} in context {} ? {}", new String[] { getAdmin().toString(), p.toString(), c.toString(), Boolean.toString(result) }); } return result; } // AdminUser != null Map<VOMSAdmin, VOMSPermission> groupPermissions = acl.getGroupPermissions(); Map<VOMSAdmin, VOMSPermission> rolePermissions = acl.getRolePermissions(); if (log.isDebugEnabled()) { log.debug("Group permissions empty? {}", groupPermissions.isEmpty()); log.debug("Role permissions empty? {}", rolePermissions.isEmpty()); } if (!groupPermissions.isEmpty()) { for (Map.Entry<VOMSAdmin, VOMSPermission> entry : groupPermissions .entrySet()) { String groupName = entry.getKey() .getDn(); if (adminVOUser.isMember(groupName)) { VOMSPermission groupPerm = entry.getValue(); effectivePerms = effectivePerms | groupPerm.getBits(); log.debug( "Adding group permission {} to admin's permission set. " + "{} is a member of group {}", new Object[] { groupPerm, adminVOUser.getFullName(), groupName }); } } } if (!rolePermissions.isEmpty()) { for (Map.Entry<VOMSAdmin, VOMSPermission> entry : rolePermissions .entrySet()) { String roleName = entry.getKey() .getDn(); log.debug("Checking if current admin has role: {}", roleName); if (adminVOUser.hasRole(roleName)) { effectivePerms = effectivePerms | entry.getValue() .getBits(); log.debug( "Adding role permission {} to admin's permission set. " + "{} has role {}", new Object[] { entry.getValue(), adminVOUser.getFullName(), roleName }); } } } VOMSPermission adminEffectivePerms = VOMSPermission .fromBits(effectivePerms); log.debug("Admin effective permissions: {}", adminEffectivePerms); boolean result = adminEffectivePerms.satisfies(p); if (log.isDebugEnabled()) { log.debug("Does {} have permissions that satisfy {} in context {} ? {}", new String[] { getAdmin().toString(), p.toString(), c.toString(), Boolean.toString(result) }); } return result; } public boolean hasPermissions(VOMSContext c, VOMSPermission p) { boolean result = false; try { result = CurrentAdminPermissionCache.INSTANCE.hasPermission(this, c, p); } catch (ExecutionException e) { log.error( "Error loading permission check result from cache: " + e.getMessage(), e); result = checkPermission(c, p); } return result; } public String getRealSubject() { SecurityContext theContext = (SecurityContext) CurrentSecurityContext.get(); return theContext.getClientName(); } public String getRealIssuer() { SecurityContext theContext = (SecurityContext) CurrentSecurityContext.get(); return theContext.getIssuerName(); } public String getRealCN() { SecurityContext theContext = (SecurityContext) CurrentSecurityContext.get(); if (theContext.getClientCert() == null) return null; String name = DNUtil.getOpenSSLSubject(theContext.getClientCert() .getSubjectX500Principal()); Matcher m = Pattern.compile("/CN=([^/]*)") .matcher(name); if (m.find()) return m.group(1); // get the CN field else return null; } public boolean hasRole(VOMSGroup group, String roleName) { VOMSRole role = VOMSRoleDAO.instance() .findByName(roleName); if (role == null) { return false; } return hasRole(group, role); } public boolean hasRole(VOMSGroup group, VOMSRole role) { if (getVoUser() == null) { return false; } if (getVoUser().isMember(group)) { return getVoUser().hasRole(group, role); } return false; } public String getRealEmailAddress() { SecurityContext theContext = (SecurityContext) CurrentSecurityContext.get(); if (theContext.getClientCert() == null) return null; String name = DNUtil.getOpenSSLSubject(theContext.getClientCert() .getSubjectX500Principal()); String candidateEmail = DNUtil .getEmailAddressFromDN(DNUtil.normalizeEmailAddressInDN(name)); if (candidateEmail == null) candidateEmail = DNUtil .getEmailAddressFromExtensions(theContext.getClientCert()); return candidateEmail; } public List<VOMSAttribute> getVOMSAttributes() { // FIXME: to be reimplemented return null; } public String toString() { return admin.toString(); } public boolean isUnauthenticated() { return admin.isUnauthenticated(); } public String getName() { return getRealSubject(); } public X509Certificate getClientCert() { if (isUnauthenticated()) { return null; } SecurityContext theContext = (SecurityContext) CurrentSecurityContext.get(); return theContext.getClientCert(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((admin == null) ? 0 : admin.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; CurrentAdmin other = (CurrentAdmin) obj; if (admin == null) { if (other.admin != null) return false; } else if (!admin.equals(other.admin)) return false; return true; } }