Skip to content
Snippets Groups Projects
Commit ec985815 authored by ale's avatar ale
Browse files

Isolate session namespaces between users

Also provide backwards compatibility for API clients that do not set
the session_id attribute, in which case the server reverts to the old
behavior (no support for multiple concurrent sessions).
parent 070c74a4
No related branches found
No related tags found
1 merge request!32Support multiple sessions for each user
...@@ -127,7 +127,6 @@ func NewKeyStore(config *Config) (*KeyStore, error) { ...@@ -127,7 +127,6 @@ func NewKeyStore(config *Config) (*KeyStore, error) {
func (s *KeyStore) expire(t time.Time) { func (s *KeyStore) expire(t time.Time) {
s.mx.Lock() s.mx.Lock()
s.userKeys.expire(t) s.userKeys.expire(t)
//s.updateKeyspaceSize()
s.mx.Unlock() s.mx.Unlock()
} }
...@@ -177,8 +176,11 @@ func (s *KeyStore) Open(ctx context.Context, username, password, sessionID strin ...@@ -177,8 +176,11 @@ func (s *KeyStore) Open(ctx context.Context, username, password, sessionID strin
} }
s.mx.Lock() s.mx.Lock()
s.userKeys.addSessionWithKey(sessionID, username, &userKey{pkey: pem}, ttlSeconds) s.userKeys.addSessionWithKey(
//s.updateKeyspaceSize() nsSessionID(username, sessionID),
username,
&userKey{pkey: pem},
ttlSeconds)
s.mx.Unlock() s.mx.Unlock()
return nil return nil
} }
...@@ -209,10 +211,10 @@ func (s *KeyStore) Get(username, ssoTicket string) ([]byte, error) { ...@@ -209,10 +211,10 @@ func (s *KeyStore) Get(username, ssoTicket string) ([]byte, error) {
// Close the user's key store and wipe the associated unencrypted key // Close the user's key store and wipe the associated unencrypted key
// from memory. Returns true if a key was actually discarded. // from memory. Returns true if a key was actually discarded.
func (s *KeyStore) Close(sessionID string) bool { func (s *KeyStore) Close(username, sessionID string) bool {
s.mx.Lock() s.mx.Lock()
defer s.mx.Unlock() defer s.mx.Unlock()
return s.userKeys.deleteSession(sessionID) return s.userKeys.deleteSession(nsSessionID(username, sessionID))
} }
func wipeBytes(b []byte) { func wipeBytes(b []byte) {
...@@ -220,3 +222,11 @@ func wipeBytes(b []byte) { ...@@ -220,3 +222,11 @@ func wipeBytes(b []byte) {
b[i] = 0 b[i] = 0
} }
} }
// Combine usernames and session IDs so that every user gets its own
// session namespace. This allows for backwards compatibility for
// clients that do not set a session_id (in which case the service
// automatically reverts to the old behavior).
func nsSessionID(username, sessionID string) string {
return username + "\000" + sessionID
}
...@@ -131,8 +131,14 @@ func TestKeystore_OpenAndGet(t *testing.T) { ...@@ -131,8 +131,14 @@ func TestKeystore_OpenAndGet(t *testing.T) {
t.Fatalf("keystore.Get() returned bad key: got %v, expected %v", result, expectedPEM) t.Fatalf("keystore.Get() returned bad key: got %v, expected %v", result, expectedPEM)
} }
// Verify user namespace isolation
keystore.Close("otheruser", "session")
if _, err := keystore.Get("testuser", ssoTicket); err != nil {
t.Fatalf("keystore.Get() returned error after Close(otheruser): %v", err)
}
// Call Close() and forget the key. // Call Close() and forget the key.
keystore.Close("session") keystore.Close("testuser", "session")
if _, err := keystore.Get("testuser", ssoTicket); err == nil { if _, err := keystore.Get("testuser", ssoTicket); err == nil {
t.Fatal("keystore.Get() returned no error after Close()") t.Fatal("keystore.Get() returned no error after Close()")
} }
...@@ -168,12 +174,12 @@ func TestKeystore_OpenAndGet_MultipleSessions(t *testing.T) { ...@@ -168,12 +174,12 @@ func TestKeystore_OpenAndGet_MultipleSessions(t *testing.T) {
} }
// Call Close() on the first session, key should still be around. // Call Close() on the first session, key should still be around.
keystore.Close("session1") keystore.Close("testuser", "session1")
if _, err := keystore.Get("testuser", ssoTicket); err != nil { if _, err := keystore.Get("testuser", ssoTicket); err != nil {
t.Fatalf("keystore.Get() after Close(session1): %v", err) t.Fatalf("keystore.Get() after Close(session1): %v", err)
} }
// Closing the second session should wipe the key. // Closing the second session should wipe the key.
keystore.Close("session2") keystore.Close("testuser", "session2")
if _, err := keystore.Get("testuser", ssoTicket); err == nil { if _, err := keystore.Get("testuser", ssoTicket); err == nil {
t.Fatal("keystore.Get() returned no error after Close(session2)") t.Fatal("keystore.Get() returned no error after Close(session2)")
} }
......
...@@ -76,7 +76,7 @@ func (s *keyStoreServer) handleClose(w http.ResponseWriter, r *http.Request) { ...@@ -76,7 +76,7 @@ func (s *keyStoreServer) handleClose(w http.ResponseWriter, r *http.Request) {
return return
} }
if s.KeyStore.Close(req.SessionID) { if s.KeyStore.Close(req.Username, req.SessionID) {
log.Printf("Close(%s): discarded key", req.Username) log.Printf("Close(%s): discarded key", req.Username)
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment