mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-20 15:07:03 +00:00
This patch contains a few changes to logging messages, to improve log readability. While at it, an obsolete TODO in the SMTP courier is removed.
134 lines
2.9 KiB
Go
134 lines
2.9 KiB
Go
// Package domaininfo implements a domain information database, to keep track
|
|
// of things we know about a particular domain.
|
|
package domaininfo
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"blitiri.com.ar/go/chasquid/internal/protoio"
|
|
"blitiri.com.ar/go/chasquid/internal/trace"
|
|
)
|
|
|
|
// Command to generate domaininfo.pb.go.
|
|
//go:generate protoc --go_out=. domaininfo.proto
|
|
|
|
type DB struct {
|
|
// Persistent store with the list of domains we know.
|
|
store *protoio.Store
|
|
|
|
info map[string]*Domain
|
|
sync.Mutex
|
|
|
|
ev *trace.EventLog
|
|
}
|
|
|
|
func New(dir string) (*DB, error) {
|
|
st, err := protoio.NewStore(dir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
l := &DB{
|
|
store: st,
|
|
info: map[string]*Domain{},
|
|
}
|
|
l.ev = trace.NewEventLog("DomainInfo", dir)
|
|
|
|
return l, nil
|
|
}
|
|
|
|
// Load the database from disk; should be called once at initialization.
|
|
func (db *DB) Load() error {
|
|
ids, err := db.store.ListIDs()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, id := range ids {
|
|
d := &Domain{}
|
|
_, err := db.store.Get(id, d)
|
|
if err != nil {
|
|
return fmt.Errorf("error loading %q: %v", id, err)
|
|
}
|
|
|
|
db.info[d.Name] = d
|
|
}
|
|
|
|
db.ev.Debugf("loaded %d domains", len(ids))
|
|
return nil
|
|
}
|
|
|
|
func (db *DB) write(d *Domain) {
|
|
err := db.store.Put(d.Name, d)
|
|
if err != nil {
|
|
db.ev.Errorf("%s error saving: %v", d.Name, err)
|
|
} else {
|
|
db.ev.Debugf("%s saved", d.Name)
|
|
}
|
|
}
|
|
|
|
// IncomingSecLevel checks an incoming security level for the domain.
|
|
// Returns true if allowed, false otherwise.
|
|
func (db *DB) IncomingSecLevel(domain string, level SecLevel) bool {
|
|
db.Lock()
|
|
defer db.Unlock()
|
|
|
|
d, exists := db.info[domain]
|
|
if !exists {
|
|
d = &Domain{Name: domain}
|
|
db.info[domain] = d
|
|
defer db.write(d)
|
|
}
|
|
|
|
if level < d.IncomingSecLevel {
|
|
db.ev.Errorf("%s incoming denied: %s < %s",
|
|
d.Name, level, d.IncomingSecLevel)
|
|
return false
|
|
} else if level == d.IncomingSecLevel {
|
|
db.ev.Debugf("%s incoming allowed: %s == %s",
|
|
d.Name, level, d.IncomingSecLevel)
|
|
return true
|
|
} else {
|
|
db.ev.Printf("%s incoming level raised: %s > %s",
|
|
d.Name, level, d.IncomingSecLevel)
|
|
d.IncomingSecLevel = level
|
|
if exists {
|
|
defer db.write(d)
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
|
|
// OutgoingSecLevel checks an incoming security level for the domain.
|
|
// Returns true if allowed, false otherwise.
|
|
func (db *DB) OutgoingSecLevel(domain string, level SecLevel) bool {
|
|
db.Lock()
|
|
defer db.Unlock()
|
|
|
|
d, exists := db.info[domain]
|
|
if !exists {
|
|
d = &Domain{Name: domain}
|
|
db.info[domain] = d
|
|
defer db.write(d)
|
|
}
|
|
|
|
if level < d.OutgoingSecLevel {
|
|
db.ev.Errorf("%s outgoing denied: %s < %s",
|
|
d.Name, level, d.OutgoingSecLevel)
|
|
return false
|
|
} else if level == d.OutgoingSecLevel {
|
|
db.ev.Debugf("%s outgoing allowed: %s == %s",
|
|
d.Name, level, d.OutgoingSecLevel)
|
|
return true
|
|
} else {
|
|
db.ev.Printf("%s outgoing level raised: %s > %s",
|
|
d.Name, level, d.OutgoingSecLevel)
|
|
d.OutgoingSecLevel = level
|
|
if exists {
|
|
defer db.write(d)
|
|
}
|
|
return true
|
|
}
|
|
}
|