mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-17 14:37:02 +00:00
There is a new protobuf library (and corresponding code generator) for Go: google.golang.org/protobuf. It is fairly compatible with the previous v1 API (github.com/golang/protobuf), but there are some changes. This patch adjusts the code and generated files to the new API. The on-wire/on-disk format remains unchanged so this should be transparent to the users.
148 lines
3.2 KiB
Go
148 lines
3.2 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=. --go_opt=paths=source_relative domaininfo.proto
|
|
|
|
// DB represents the persistent domain information database.
|
|
type DB struct {
|
|
// Persistent store with the list of domains we know.
|
|
store *protoio.Store
|
|
|
|
info map[string]*Domain
|
|
sync.Mutex
|
|
|
|
ev *trace.EventLog
|
|
}
|
|
|
|
// New opens a domain information database on the given dir, creating it if
|
|
// necessary. The returned database will not be loaded.
|
|
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)
|
|
|
|
err = l.Reload()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return l, nil
|
|
}
|
|
|
|
// Reload the database from disk.
|
|
func (db *DB) Reload() error {
|
|
db.Lock()
|
|
defer db.Unlock()
|
|
|
|
// Clear the map, in case it has data.
|
|
db.info = map[string]*Domain{}
|
|
|
|
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
|
|
}
|
|
}
|