user mgmt

This commit is contained in:
Miek Gieben 2012-08-07 20:24:57 +02:00
parent 7e213aea0d
commit 468348fc28
4 changed files with 49 additions and 39 deletions

View File

@ -15,22 +15,9 @@ In zone we have:
(This will probably all change and use more consistent names)
## Add zones
Add from file:
ZONE. TXT "READ origin /path/to/zone"
Add from axfr:
ZONE. TXT "READXFR origin ip(6)-of-master [tsig-secret]"
## Delete zones
ZONE. TXT "DROP origin"
## List zones
ZONE. TXT "list"
Zones are listed in the additional section of the reply packet
@ -40,12 +27,7 @@ Zones are listed in the additional section of the reply packet
# USER
## Add user
USER. TXT "ADD miekg [tsig-secret]"
USER. TXT "ADD miekg hmac:base64-tsig-secret"
USER. TXT "DROP miekg"
USER. TXT "ADDRIGHT miekg list" // list/write/drop/right
USER. TXT "ADDRIGHT miekg list" // list/write/drop/user
USER. TXT "DROPRIGHT miekg list"

View File

@ -3,6 +3,7 @@ package main
import (
"dns"
"strings"
"time"
)
const (
@ -15,7 +16,6 @@ const (
// fks config
type Config struct {
Zones map[string]*dns.Zone // All zones we are authoritative for
Users map[string]bool // All known users
Tsigs map[string]string // Tsig keys for all users
Rights map[string]int // Rights for all users
}
@ -23,7 +23,6 @@ type Config struct {
func NewConfig() *Config {
c := new(Config)
c.Zones = make(map[string]*dns.Zone)
c.Users = make(map[string]bool)
c.Tsigs = make(map[string]string)
c.Rights = make(map[string]int)
return c
@ -31,29 +30,56 @@ func NewConfig() *Config {
func formerr(w dns.ResponseWriter, req *dns.Msg) {
m := new(dns.Msg)
m.MsgHdr.Opcode = dns.OpcodeUpdate
if req.IsTsig() {
m.SetTsig(tsig(req), dns.HmacMD5, 300, time.Now().Unix())
}
w.Write(m.SetRcode(req, dns.RcodeFormatError))
}
func noerr(w dns.ResponseWriter, req *dns.Msg) {
m := new(dns.Msg)
m.MsgHdr.Opcode = dns.OpcodeUpdate
m.SetTsig(tsig(req), dns.HmacMD5, 300, time.Now().Unix())
w.Write(m.SetReply(req))
}
func config(w dns.ResponseWriter, req *dns.Msg, c *Config) {
// Set question to fks. IN TXT otherwise error
// tsig signed, key = user
// config stuff in Auth section (just as dynamic updates (*hint* *hint*)
// SUBSYSTEM. IN TXT "OPERATION<SPACE>OPTIONS..."
// ZONE. IN TXT "READ origin /z/bloep" - absolute path in fs
func tsig(req *dns.Msg) string {
return req.Extra[len(req.Extra)-1].Header().Name
}
if !req.IsUpdate() {
logPrintf("non config command")
// Check if the user has any rights
func configRights(user string, c *Config) {
}
// config stuff in Auth section (just as dynamic updates (*hint* *hint*)
// SUBSYSTEM. IN TXT "OPERATION<SPACE>OPTIONS..."
// ZONE. IN TXT "READ origin /z/bloep" - absolute path in fs
func config(w dns.ResponseWriter, req *dns.Msg, c *Config) {
logPrintf("config command")
if !req.IsTsig() {
logPrintf("non config command (no tsig)")
formerr(w, req)
return
}
// TODO: check tsig
logPrintf("config commmand")
if !req.IsUpdate() {
logPrintf("non config command (no update)")
formerr(w, req)
return
}
if w.TsigStatus() != nil {
logPrintf("non config command (tsig fail)")
formerr(w, req)
return
}
// No need to check the user, if the tsig checks out, the user exists
logPrintf("config command ok")
for _, rr := range req.Ns {
t, ok := rr.(*dns.RR_TXT)
@ -128,6 +154,7 @@ func configZONE(w dns.ResponseWriter, req *dns.Msg, t *dns.RR_TXT, c *Config) er
a, _ := dns.NewRR("ZONE. TXT \"" + zone + "\"")
m.Extra = append(m.Extra, a)
}
m.SetTsig(tsig(req), dns.HmacMD5, 300, time.Now().Unix())
w.Write(m)
}
return nil

View File

@ -5,17 +5,23 @@ import (
"flag"
"log"
"os"
"strings"
)
var (
flaglog = flag.Bool("log", false, "log incoming queries")
superuser = flag.String("user", "root", "username to use for the superuser")
superkey = flag.String("key", dns.HmacSHA1+":c3R1cGlk", "tsig [hmac:base64] key for superuser authentication")
superkey = flag.String("key", "c3R1cGlk", "base64 tsig key for superuser authentication")
)
func main() {
flag.Parse()
conf := NewConfig()
*superuser = strings.ToLower(*superuser)
conf.Users[*superuser] = true
conf.Tsigs[dns.Fqdn(*superuser)] = *superkey
conf.Rights[*superuser] = R_LIST | R_WRITE | R_DROP | R_USER // *all* of them
go func() {
err := dns.ListenAndServe(":1053", "udp", nil)
if err != nil {
@ -23,14 +29,11 @@ func main() {
}
}()
go func() {
err := dns.ListenAndServe(":8053", "tcp", nil)
err := dns.ListenAndServeTsig(":8053", "tcp", nil, conf.Tsigs)
if err != nil {
log.Fatal("fksd: could not start config listener: %s", err.Error())
}
}()
conf.Users[*superuser] = true
conf.Tsigs[*superuser] = superkey
conf.Rights[*superuser] = R_LIST | R_WRITE | R_DROP | R_USER // *all* of them
// Yes, we HIJACK zone. ... not sure on how to make this "private"
dns.HandleFunc("ZONE.", func(w dns.ResponseWriter, req *dns.Msg) { config(w, req, conf) })
// Gasp!! And USER.

View File

@ -214,7 +214,6 @@ func (srv *Server) ListenAndServe() error {
// ServeTCP starts a TCP listener for the server.
// Each request is handled in a seperate goroutine.
// with the Handler set in ....
func (srv *Server) ServeTCP(l *net.TCPListener) error {
defer l.Close()
handler := srv.Handler
@ -267,7 +266,6 @@ forever:
// ServeUDP starts a UDP listener for the server.
// Each request is handled in a seperate goroutine,
// with the Handler set in ....
func (srv *Server) ServeUDP(l *net.UDPConn) error {
defer l.Close()
handler := srv.Handler