001 /* 002 * Cumulus4j - Securing your data in the cloud - http://cumulus4j.org 003 * Copyright (C) 2011 NightLabs Consulting GmbH 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 package org.cumulus4j.keymanager; 019 020 import java.util.Arrays; 021 import java.util.Date; 022 023 import org.cumulus4j.keymanager.back.shared.IdentifierUtil; 024 import org.slf4j.Logger; 025 import org.slf4j.LoggerFactory; 026 027 /** 028 * <p> 029 * Session to control and restrict the key exchange with the application server. 030 * </p> 031 * <p> 032 * In order to protect the keys as well as possible, keys can only be requested from an application 033 * server within the scope of a so-called crypto-session. The client controls when to open/close a crypto-session 034 * and when to allow keys to be transferred. Key transfer is only possible while a session is {@link #setReleased(boolean) unlocked}. 035 * </p> 036 * <p> 037 * This is not API! Use the classes and interfaces provided by <code>org.cumulus4j.keymanager.api</code> instead. 038 * </p> 039 * 040 * @author Marco หงุ่ยตระกูล-Schulze - marco at nightlabs dot de 041 */ 042 public class Session 043 { 044 private static final Logger logger = LoggerFactory.getLogger(Session.class); 045 046 private SessionManager sessionManager; 047 048 protected Session(SessionManager sessionManager, String userName, char[] password) 049 { 050 if (sessionManager == null) 051 throw new IllegalArgumentException("sessionManager == null"); 052 053 if (userName == null) 054 throw new IllegalArgumentException("userName == null"); 055 056 if (password == null) 057 throw new IllegalArgumentException("password == null"); 058 059 this.sessionManager = sessionManager; 060 061 this.cryptoSessionID = ( 062 sessionManager.getCryptoSessionIDPrefix() 063 + '.' 064 + Long.toString(sessionManager.nextCryptoSessionSerial(), 36) 065 + '.' 066 + IdentifierUtil.createRandomID(8) 067 ); 068 069 this.userName = userName; 070 // Clone to prevent the password in the session from being nulled, when the outside password is nulled 071 // or the outside password from being corrupted when this session is closed. Marco :-) 072 this.password = password.clone(); 073 } 074 075 private String cryptoSessionID; 076 private String userName; 077 private char[] password; 078 private volatile Date lastUse; 079 private volatile Date expiry; 080 private volatile boolean released; 081 082 /** 083 * Get the identifier of this session. 084 * @return the session's unique identifier. 085 */ 086 public String getCryptoSessionID() { 087 return cryptoSessionID; 088 } 089 090 public String getUserName() { 091 return userName; 092 } 093 public char[] getPassword() { 094 return password; 095 } 096 097 public Date getLastUse() { 098 return lastUse; 099 } 100 101 protected void updateLastUse(long expiryAgeMSec) { 102 lastUse = new Date(); 103 expiry = new Date(lastUse.getTime() + expiryAgeMSec); 104 } 105 106 public Date getExpiry() { 107 return expiry; 108 } 109 110 public void destroy() 111 { 112 SessionManager sm = sessionManager; 113 if (sm == null) 114 return; 115 116 sm.onDestroySession(this); 117 118 sessionManager = null; 119 120 logger.debug("destroy: Destroying session for userName='{}' cryptoSessionID='{}'.", userName, cryptoSessionID); 121 122 char[] pw = password; 123 if (pw != null) { 124 Arrays.fill(pw, (char)0); 125 password = null; 126 } 127 128 cryptoSessionID = null; 129 userName = null; 130 } 131 132 /** 133 * <p> 134 * Set the 'released' status. 135 * </p> 136 * <p> 137 * The application server can only request keys from a session that is currently acquired. That means, a session 138 * should first be acquired, then the app-server should be made to work (on behalf of the client) and finally, 139 * it should be released again. 140 * </p> 141 * 142 * @param released the new 'released' status. 143 */ 144 protected void setReleased(boolean released) { 145 this.released = released; 146 } 147 148 public void release() { 149 SessionManager sm = sessionManager; 150 if (sm == null) 151 return; 152 153 sm.onReleaseSession(this); 154 } 155 156 public boolean isReleased() { 157 return released; 158 } 159 160 public void reacquire() { 161 SessionManager sm = sessionManager; 162 if (sm == null) 163 return; 164 165 sm.onReacquireSession(this); 166 } 167 }