Files

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
}