blob: d6c4012b4ed52a1d0b2188f0d2f107bb306bbc81 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You 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.apache.geode.internal.cache.tier.sockets;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.subject.Subject;
import org.apache.geode.annotations.VisibleForTesting;
import org.apache.geode.internal.security.AuthorizeRequest;
import org.apache.geode.internal.security.AuthorizeRequestPP;
import org.apache.geode.logging.internal.log4j.api.LogService;
public class ClientUserAuths {
private static final Logger logger = LogService.getLogger();
// private AtomicLong counter = new AtomicLong(1);
private Random uniqueIdGenerator = null;
private int m_seed;
private long m_firstId;
private ConcurrentHashMap<Long, UserAuthAttributes> uniqueIdVsUserAuth =
new ConcurrentHashMap<Long, UserAuthAttributes>();
private ConcurrentHashMap<String, UserAuthAttributes> cqNameVsUserAuth =
new ConcurrentHashMap<String, UserAuthAttributes>();
private ConcurrentHashMap<Long, Subject> uniqueIdVsSubject =
new ConcurrentHashMap<Long, Subject>();
public long putUserAuth(UserAuthAttributes userAuthAttr) {
// TODO:hitesh should we do random here
// long newId = counter.getAndIncrement();
long newId = getNextID();
uniqueIdVsUserAuth.put(newId, userAuthAttr);
return newId;
}
public long putSubject(Subject subject) {
long newId = getNextID();
uniqueIdVsSubject.put(newId, subject);
logger.debug("Subject of {} added.", newId);
return newId;
}
public ClientUserAuths(int clientProxyHashcode) {
m_seed = clientProxyHashcode;
uniqueIdGenerator = new Random(m_seed + System.currentTimeMillis());
m_firstId = uniqueIdGenerator.nextLong();
}
private synchronized long getNextID() {
long uniqueId = uniqueIdGenerator.nextLong();
if (uniqueId == m_firstId) {
uniqueIdGenerator = new Random(m_seed + System.currentTimeMillis());
m_firstId = uniqueIdGenerator.nextLong();
// now every user need to reauthenticate as we are short of Ids..
// though possibility of this is rare.
uniqueIdVsUserAuth.clear();
return m_firstId;
}
return uniqueId;
}
public UserAuthAttributes getUserAuthAttributes(long userId) {
return uniqueIdVsUserAuth.get(userId);
}
@VisibleForTesting
protected Collection<Subject> getSubjects() {
return Collections.unmodifiableCollection(this.uniqueIdVsSubject.values());
}
public Subject getSubject(long userId) {
return uniqueIdVsSubject.get(userId);
}
public boolean removeSubject(long userId) {
Subject subject = uniqueIdVsSubject.remove(userId);
logger.debug("Subject of {} removed.", userId);
if (subject == null)
return false;
subject.logout();
return true;
}
public UserAuthAttributes getUserAuthAttributes(String cqName) {
// Long uniqueId = cqNameVsUserAuth.get(cqName);
// return uniqueIdVsUserAuth.get(uniqueId);
return cqNameVsUserAuth.get(cqName);
}
public void setUserAuthAttributesForCq(String cqName, long uniqueId, boolean isDurable) {
UserAuthAttributes uaa = this.uniqueIdVsUserAuth.get(uniqueId);
if (uaa != null) {
if (!isDurable)
this.cqNameVsUserAuth.put(cqName, uaa);
else {
UserAuthAttributes oldUaa = this.cqNameVsUserAuth.put(cqName, uaa);
if (oldUaa != null) {
if (oldUaa != uaa)// clean earlier one
{
this.cleanUserAuth(oldUaa);
// add durable(increment)
uaa.setDurable();
} else {
// if looks extra call from client
}
} else {
uaa.setDurable();
}
}
}
}
public void removeUserAuthAttributesForCq(String cqName, boolean isDurable) {
UserAuthAttributes uaa = this.cqNameVsUserAuth.remove(cqName);
if (uaa != null && isDurable)
uaa.unsetDurable();
}
public boolean removeUserId(long userId, boolean keepAlive) {
UserAuthAttributes uaa = uniqueIdVsUserAuth.get(userId);
if (uaa != null && !(uaa.isDurable() && keepAlive)) {
uaa = uniqueIdVsUserAuth.remove(userId);
logger.debug("UserAuth of {} removed.");
if (uaa != null) {
cleanUserAuth(uaa);
return true;
}
}
return false;
}
public void cleanUserAuth(UserAuthAttributes userAuth) {
if (userAuth != null) {
AuthorizeRequest authReq = userAuth.getAuthzRequest();
try {
if (authReq != null) {
authReq.close();
authReq = null;
}
} catch (Exception ex) {
// TODO:hitesh
/*
* if (securityLogger.warningEnabled()) { securityLogger.warning( LocalizedStrings.
* String.
* format("%s: An exception was thrown while closing client authorization callback. %s",
* new Object[] {"", ex})); }
*/
}
try {
AuthorizeRequestPP postAuthzReq = userAuth.getPostAuthzRequest();
if (postAuthzReq != null) {
postAuthzReq.close();
postAuthzReq = null;
}
} catch (Exception ex) {
// TODO:hitesh
/*
* if (securityLogger.warningEnabled()) { securityLogger.warning( LocalizedStrings.
* String.
* format("%s: An exception was thrown while closing client post-process authorization callback. %s"
* ,
* new Object[] {"", ex})); }
*/
}
}
}
public void cleanup(boolean fromCacheClientProxy) {
for (UserAuthAttributes userAuth : this.uniqueIdVsUserAuth.values()) {
// isDurable is checked for multiuser in CQ
if (!fromCacheClientProxy && !userAuth.isDurable()) {// from serverConnection class
cleanUserAuth(userAuth);
} else if (fromCacheClientProxy && userAuth.isDurable()) {// from cacheclientProxy class
cleanUserAuth(userAuth);
}
}
// Logout the subjects
for (Long subjectId : uniqueIdVsSubject.keySet()) {
removeSubject(subjectId);
}
}
public void fillPreviousCQAuth(ClientUserAuths previousClientUserAuths) {
for (Iterator<Map.Entry<String, UserAuthAttributes>> iter =
previousClientUserAuths.cqNameVsUserAuth.entrySet().iterator(); iter.hasNext();) {
Map.Entry<String, UserAuthAttributes> ent = iter.next();
String cqName = ent.getKey();
UserAuthAttributes prevUaa = ent.getValue();
UserAuthAttributes newUaa = this.cqNameVsUserAuth.putIfAbsent(cqName, prevUaa);
if (newUaa != null) {
previousClientUserAuths.cleanUserAuth(prevUaa);
}
}
}
}