SessionInfo info = getSessionInfo(secretSessionId);
if (info != null) { // authentication succeeded
updateConnectQos(info, connectQos);
ConnectReturnQosServer returnQos = new ConnectReturnQosServer(glob, info.getConnectQos().getData());
returnQos.getSessionQos().setSecretSessionId(secretSessionId);
returnQos.getSessionQos().setSessionName(info.getSessionName());
returnQos.setReconnected(true);
returnQos.getData().addClientProperty(Constants.CLIENTPROPERTY_RCVTIMESTAMPSTR, IsoDateParser.getCurrentUTCTimestampNanos());
log.info("Reconnected with given secretSessionId.");
return returnQos;
}
}
}
catch (Throwable e) {
log.severe("Internal error when trying to reconnect to session " + connectQos.getSessionName() + " with secret session ID: " + e.toString());
e.printStackTrace();
throw XmlBlasterException.convert(glob, ME, ErrorCode.INTERNAL_CONNECTIONFAILURE.toString(), e);
}
// [2] Try reconnecting with publicSessionId
if (connectQos.hasPublicSessionId()) {
SessionInfo info = getSessionInfo(connectQos.getSessionName());
if (info != null && !info.isShutdown() && !info.getConnectQos().bypassCredentialCheck()) {
if (connectQos.getSessionQos().reconnectSameClientOnly()) {
String text = "Only the creator of session " + connectQos.getSessionName().toString() + " may reconnect, access denied.";
log.warning(text);
throw new XmlBlasterException(glob, ErrorCode.USER_CONFIGURATION_IDENTICALCLIENT,
ME+".connect()", text);
}
try {
// Check password as we can't trust the public session ID
connectQos = info.getSecuritySession().init(connectQos, null);
boolean ok = info.getSecuritySession().verify(connectQos.getSecurityQos());
if (!ok)
throw new XmlBlasterException(glob, ErrorCode.USER_SECURITY_AUTHENTICATION_ACCESSDENIED,
ME, "Access denied for " + connectQos.getSecurityQos().getUserId() + " " + connectQos.getClientPluginType());
String oldSecretSessionId = info.getSecretSessionId();
if (secretSessionId == null || secretSessionId.length() < 2) {
// Keep the old secretSessionId
connectQos.getSessionQos().setSecretSessionId(oldSecretSessionId);
}
else {
// The CORBA driver insists in a new secretSessionId
changeSecretSessionId(oldSecretSessionId, secretSessionId);
connectQos.getSessionQos().setSecretSessionId(secretSessionId);
}
updateConnectQos(info, connectQos); // fires event
ConnectReturnQosServer returnQos = new ConnectReturnQosServer(glob, info.getConnectQos().getData());
returnQos.getSessionQos().setSessionName(info.getSessionName());
returnQos.setReconnected(true);
returnQos.getData().addClientProperty(Constants.CLIENTPROPERTY_RCVTIMESTAMPSTR, IsoDateParser.getCurrentUTCTimestampNanos());
log.info("Reconnected with given publicSessionId to '" + info.getSessionName() + "'.");
return returnQos;
}
catch (XmlBlasterException e) {
log.warning("Access is denied when trying to reconnect to session " + info.getSessionName() + ": " + e.getMessage());
throw e; // Thrown if authentication failed
}
catch (Throwable e) {
log.severe("Internal error when trying to reconnect to session " + info.getSessionName() + " with public session ID: " + e.toString());
e.printStackTrace();
throw XmlBlasterException.convert(glob, ME, ErrorCode.INTERNAL_CONNECTIONFAILURE.toString(), e);
}
}
}
// [3] Generate a secret session ID
if (secretSessionId == null || secretSessionId.length() < 2) {
secretSessionId = createSessionId("null" /*subjectCtx.getName()*/);
connectQos.getSessionQos().setSecretSessionId(secretSessionId); // assure consistency
if (log.isLoggable(Level.FINE)) log.fine("Empty secretSessionId - generated secretSessionId=" + secretSessionId);
}
I_Session sessionCtx = null;
I_Manager securityMgr = null;
SessionInfo sessionInfo = null;
// [4] Authenticate new client with password
try {
// Get suitable SecurityManager and context ...
securityMgr = plgnLdr.getManager(connectQos.getClientPluginType(), connectQos.getClientPluginVersion());
if (securityMgr == null) {
log.warning("Access is denied, there is no security manager configured for this connect QoS: " + connectQos.toXml());
throw new XmlBlasterException(glob, ErrorCode.USER_SECURITY_AUTHENTICATION_ACCESSDENIED, ME, "There is no security manager configured with the given connect QoS");
}
sessionCtx = securityMgr.reserveSession(secretSessionId); // always creates a new I_Session instance
connectQos = sessionCtx.init(connectQos, null);
if (connectQos.bypassCredentialCheck()) {
// This happens when a session is auto created by a PtP message
// Only ConnectQosServer (which is under control of the core) can set this flag
if (log.isLoggable(Level.FINE)) log.fine("SECURITY SWITCH OFF: Granted access to xmlBlaster without password, bypassCredentialCheck=true");
}
else {
String securityInfo = sessionCtx.init(connectQos.getSecurityQos()); // throws XmlBlasterExceptions if authentication fails
if (securityInfo != null && securityInfo.length() > 1) log.warning("Ignoring security info: " + securityInfo);
}
// Now the client is authenticated
}
catch (XmlBlasterException e) {
// If access is denied: cleanup resources
log.warning("Access is denied: " + e.getMessage() + ": " + connectQos.toString());
if (securityMgr != null) securityMgr.releaseSession(secretSessionId, null); // allways creates a new I_Session instance
throw e;
}
catch (Throwable e) {
log.severe("PANIC: Access is denied: " + e.getMessage() + "\n" + ServerScope.getStackTraceAsString(e));
e.printStackTrace();
// On error: cleanup resources
securityMgr.releaseSession(secretSessionId, null); // allways creates a new I_Session instance
throw XmlBlasterException.convert(glob, ME, ErrorCode.INTERNAL_CONNECTIONFAILURE.toString(), e);
}
if (log.isLoggable(Level.FINE)) log.fine("Checking if user is known ...");
SubjectInfo subjectInfo = null;
try {
/*
// Check if user is known, otherwise create an entry ...
I_Subject subjectCtx = sessionCtx.getSubject();
SessionName subjectName = new SessionName(glob, connectQos.getSessionName(), 0L); // Force to be of type subject (no public session ID)
boolean subjectIsAlive = false;
synchronized(this.loginNameSubjectInfoMap) { // Protect against two simultaneous logins
subjectInfo = (SubjectInfo)this.loginNameSubjectInfoMap.get(subjectName.getLoginName());
//log.error(ME, "DEBUG ONLY, subjectName=" + subjectName.toString() + " loginName=" + subjectName.getLoginName() + " state=" + toXml());
if (subjectInfo == null) {
subjectInfo = new SubjectInfo(getGlobal(), this, subjectName);
this.loginNameSubjectInfoMap.put(subjectInfo.getLoginName(), subjectInfo); // Protect against two simultaneous logins
}
subjectIsAlive = subjectInfo.isAlive();
} // synchronized(this.loginNameSubjectInfoMap)
if (!subjectInfo.isAlive()) {
try {
subjectInfo.toAlive(subjectCtx, connectQos.getSubjectQueueProperty());
}
catch(Throwable e) {
synchronized(this.loginNameSubjectInfoMap) {
this.loginNameSubjectInfoMap.remove(subjectInfo.getLoginName());
}
throw e;
}
}
*/
// [5] New client is authenticated, create the SessioInfo
boolean returnLocked = true;
subjectInfo = getOrCreateSubjectInfoByName(connectQos.getSessionName(),
returnLocked, sessionCtx.getSubject(), connectQos.getSubjectQueueProperty());
try { // subjectInfo.getLock().release())
if (subjectInfo.isAlive()) {
if (connectQos.getData().hasSubjectQueueProperty())
subjectInfo.setSubjectQueueProperty(connectQos.getSubjectQueueProperty()); // overwrites only if not null
}
// Check if client does a relogin and wants to destroy old sessions
if (connectQos.clearSessions() == true) {
SessionInfo[] sessions = subjectInfo.getSessionsToClear(connectQos);
if (sessions.length > 0) {
for (int i=0; i<sessions.length; i++ ) {
SessionInfo si = sessions[i];
log.warning("Destroying session '" + si.getSecretSessionId() + "' of user '" + subjectInfo.getSubjectName() + "' as requested by client");
disconnect(si.getSecretSessionId(), (String)null);
}
// will create a new SubjectInfo instance (which should be OK)
return connect(connectQos, secretSessionId);
}
}
if (log.isLoggable(Level.FINE)) log.fine("Creating sessionInfo for " + subjectInfo.getId());
// A PtP with forceQueuing=true and a simultaneous connect of the same
// client: This code is thread safe with new SessionInfo() below
// to avoid duplicate SessionInfo
sessionInfo = getOrCreateSessionInfo(connectQos.getSessionName(), connectQos);
if (sessionInfo.isInitialized() &&
!sessionInfo.isShutdown() && sessionInfo.getConnectQos().bypassCredentialCheck()) {
if (log.isLoggable(Level.FINE)) log.fine("connect: Reused session with had bypassCredentialCheck=true");
String oldSecretSessionId = sessionInfo.getSecretSessionId();
sessionInfo.setSecuritySession(sessionCtx);
if (secretSessionId == null || secretSessionId.length() < 2) {
// Keep the old secretSessionId
connectQos.getSessionQos().setSecretSessionId(oldSecretSessionId);
}
else {
// The CORBA driver insists in a new secretSessionId
changeSecretSessionId(oldSecretSessionId, secretSessionId);
connectQos.getSessionQos().setSecretSessionId(secretSessionId);
}
updateConnectQos(sessionInfo, connectQos);
}
else {
// Create the new sessionInfo instance
if (log.isLoggable(Level.FINE)) log.fine("connect: sessionId='" + secretSessionId + "' connectQos='" + connectQos.toXml() + "'");
sessionInfo.init(subjectInfo, sessionCtx, connectQos);
synchronized(this.sessionInfoMap) {
this.sessionInfoMap.put(secretSessionId, sessionInfo);
}
}
connectQos.getSessionQos().setSecretSessionId(secretSessionId);
connectQos.getSessionQos().setSessionName(sessionInfo.getSessionName());
subjectInfo.notifyAboutLogin(sessionInfo);
fireClientEvent(sessionInfo, true);
}
finally {
if (subjectInfo != null) subjectInfo.getLock().release();
}
// --- compose an answer -----------------------------------------------
ConnectReturnQosServer returnQos = new ConnectReturnQosServer(glob, connectQos.getData());
returnQos.getSessionQos().setSecretSessionId(secretSessionId); // securityInfo is not coded yet !
returnQos.getSessionQos().setSessionName(sessionInfo.getSessionName());
returnQos.getData().addClientProperty(Constants.CLIENTPROPERTY_RCVTIMESTAMPSTR, IsoDateParser.getCurrentUTCTimestampNanos());
// Now some nice logging ...
StringBuffer sb = new StringBuffer(256);
if (connectQos.bypassCredentialCheck())
sb.append("Created tempory session for client ");
else
sb.append("Successful login for client ");
sb.append(sessionInfo.getSessionName().getAbsoluteName());
sb.append(", session");
sb.append(((connectQos.getSessionTimeout() > 0L) ?
" expires after"+Timestamp.millisToNice(connectQos.getSessionTimeout()) :
" lasts forever"));
sb.append(", ").append(subjectInfo.getNumSessions()).append(" of ");
sb.append(connectQos.getMaxSessions()).append(" sessions are in use.");
log.info(sb.toString());
if (log.isLoggable(Level.FINEST)) log.finest(toXml());
if (log.isLoggable(Level.FINEST)) log.finest("Returned QoS:\n" + returnQos.toXml());
if (log.isLoggable(Level.FINER)) log.finer("Leaving connect()");
return returnQos;
}
catch (XmlBlasterException e) {