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 // see org.cumulus4j.keymanager.back.shared.Request#getCryptoSessionIDPrefix() 062 // see org.cumulus4j.store.crypto.AbstractCryptoSession#getKeyStoreID() 063 this.cryptoSessionID = ( 064 sessionManager.getCryptoSessionIDPrefix() 065 + '*' 066 + Long.toString(sessionManager.nextCryptoSessionSerial(), 36) 067 + '*' 068 + IdentifierUtil.createRandomID(6) 069 ); 070 071 this.userName = userName; 072 // Clone to prevent the password in the session from being nulled, when the outside password is nulled 073 // or the outside password from being corrupted when this session is closed. Marco :-) 074 this.password = password.clone(); 075 } 076 077 private String cryptoSessionID; 078 private String userName; 079 private char[] password; 080 private volatile Date lastUse; 081 private volatile Date expiry; 082 private volatile boolean released; 083 084 /** 085 * Get the identifier of this session. 086 * @return the session's unique identifier. 087 */ 088 public String getCryptoSessionID() { 089 return cryptoSessionID; 090 } 091 092 public String getUserName() { 093 return userName; 094 } 095 public char[] getPassword() { 096 return password; 097 } 098 099 public Date getLastUse() { 100 return lastUse; 101 } 102 103 protected void updateLastUse(long expiryAgeMSec) { 104 lastUse = new Date(); 105 expiry = new Date(lastUse.getTime() + expiryAgeMSec); 106 } 107 108 public Date getExpiry() { 109 return expiry; 110 } 111 112 public void destroy() 113 { 114 SessionManager sm = sessionManager; 115 if (sm == null) 116 return; 117 118 sm.onDestroySession(this); 119 120 sessionManager = null; 121 122 logger.debug("destroy: Destroying session for userName='{}' cryptoSessionID='{}'.", userName, cryptoSessionID); 123 124 char[] pw = password; 125 if (pw != null) { 126 Arrays.fill(pw, (char)0); 127 password = null; 128 } 129 130 cryptoSessionID = null; 131 userName = null; 132 } 133 134 /** 135 * <p> 136 * Set the 'released' status. 137 * </p> 138 * <p> 139 * The application server can only request keys from a session that is currently acquired. That means, a session 140 * should first be acquired, then the app-server should be made to work (on behalf of the client) and finally, 141 * it should be released again. 142 * </p> 143 * 144 * @param released the new 'released' status. 145 */ 146 protected void setReleased(boolean released) { 147 this.released = released; 148 } 149 150 public void release() { 151 SessionManager sm = sessionManager; 152 if (sm == null) 153 return; 154 155 sm.onReleaseSession(this); 156 } 157 158 public boolean isReleased() { 159 return released; 160 } 161 162 public void reacquire() { 163 SessionManager sm = sessionManager; 164 if (sm == null) 165 return; 166 167 sm.onReacquireSession(this); 168 } 169 }