65 lines
1.9 KiB
Go
65 lines
1.9 KiB
Go
package webui
|
|
|
|
import (
|
|
"net/http"
|
|
"sync"
|
|
|
|
"github.com/ProtonMail/go-crypto/openpgp"
|
|
)
|
|
|
|
// pgpKeyCache holds unlocked PGP identities for the rest of a login session —
|
|
// mirrors smimeKeyCache (webmail_smime_cache.go), but caches the whole *openpgp.Entity
|
|
// (not just a raw private key) since decrypting a PGP message needs subkey lookup on
|
|
// the entity itself, not a bare key value. Kept as its own type rather than
|
|
// generalizing smimeKeyCache into an any-typed cache — both stay simply and
|
|
// correctly typed.
|
|
type pgpKeyCache struct {
|
|
mu sync.Mutex
|
|
byTok map[string]map[int64]*openpgp.Entity
|
|
}
|
|
|
|
func newPGPKeyCache() *pgpKeyCache {
|
|
return &pgpKeyCache{byTok: map[string]map[int64]*openpgp.Entity{}}
|
|
}
|
|
|
|
func (c *pgpKeyCache) get(token string, identityID int64) (*openpgp.Entity, bool) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
keys, ok := c.byTok[token]
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
entity, ok := keys[identityID]
|
|
return entity, ok
|
|
}
|
|
|
|
func (c *pgpKeyCache) put(token string, identityID int64, entity *openpgp.Entity) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
if c.byTok[token] == nil {
|
|
c.byTok[token] = map[int64]*openpgp.Entity{}
|
|
}
|
|
c.byTok[token][identityID] = entity
|
|
}
|
|
|
|
// clearSession drops every unlocked identity for one session — called on logout so
|
|
// a key never outlives the session it was unlocked in. Same ponytail-flagged
|
|
// simplification as smimeKeyCache.clearSession: memory-bounded by active sessions,
|
|
// not TTL'd against a session that expires without an explicit logout.
|
|
func (c *pgpKeyCache) clearSession(token string) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
delete(c.byTok, token)
|
|
}
|
|
|
|
// sessionToken reads the raw webmail session cookie value, used as the PGP key
|
|
// cache's key — separate from mailboxFromContext, which only exposes the resolved
|
|
// *db.Mailbox, not the token itself.
|
|
func sessionToken(r *http.Request) string {
|
|
c, err := r.Cookie(mailboxSessionCookieName)
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
return c.Value
|
|
}
|