Split services into family

This commit is contained in:
nemunaire 2020-10-10 18:44:17 +02:00
parent f64c93e08b
commit bb54496ca5
23 changed files with 606 additions and 168 deletions

View File

@ -48,6 +48,7 @@ import (
"git.happydns.org/happydns/config"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/services"
"git.happydns.org/happydns/services/abstract"
"git.happydns.org/happydns/sources"
"git.happydns.org/happydns/storage"
)
@ -339,7 +340,7 @@ func applyZone(opts *config.Options, req *RequestResources, body io.Reader) Resp
// Update serial
if newSOA != nil {
for _, svc := range req.Zone.Services[""] {
if origin, ok := svc.Service.(*svcs.Origin); ok {
if origin, ok := svc.Service.(*abstract.Origin); ok {
origin.Serial = newSOA.Serial
break
}

View File

@ -55,6 +55,8 @@ import (
_ "git.happydns.org/happydns/sources/gandi"
_ "git.happydns.org/happydns/sources/ovh"
_ "git.happydns.org/happydns/services/providers/google"
_ "git.happydns.org/happydns/storage/leveldb"
)

View File

@ -29,7 +29,7 @@
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
package abstract
import (
"strings"
@ -37,6 +37,7 @@ import (
"github.com/miekg/dns"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/services"
"git.happydns.org/happydns/utils"
)
@ -65,8 +66,8 @@ func (s *ACMEChallenge) GenRRs(domain string, ttl uint32, origin string) (rrs []
return
}
func acmechallenge_analyze(a *Analyzer) error {
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeTXT, Prefix: "_acme-challenge"}) {
func acmechallenge_analyze(a *svcs.Analyzer) error {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeTXT, Prefix: "_acme-challenge"}) {
domain := strings.TrimPrefix(record.Header().Name, "_acme-challenge.")
if txt, ok := record.(*dns.TXT); ok {
a.UseRR(record, domain, &ACMEChallenge{
@ -78,19 +79,20 @@ func acmechallenge_analyze(a *Analyzer) error {
}
func init() {
RegisterService(
svcs.RegisterService(
func() happydns.Service {
return &ACMEChallenge{}
},
acmechallenge_analyze,
ServiceInfos{
svcs.ServiceInfos{
Name: "ACME Challenge",
Description: "Temporary record to prove that you are in possession of the sub-domain.",
Family: svcs.Abstract,
Categories: []string{
"temporary",
"tls",
},
Restrictions: ServiceRestrictions{
Restrictions: svcs.ServiceRestrictions{
NearAlone: true,
},
},

View File

@ -29,7 +29,7 @@
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
package abstract
import (
"fmt"
@ -37,19 +37,13 @@ import (
"github.com/miekg/dns"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/services"
"git.happydns.org/happydns/utils"
)
type DS struct {
KeyTag uint16 `json:"keytag" happydns:"label=Key Tag"`
Algorithm uint8 `json:"algorithm" happydns:"label=Algorithm"`
DigestType uint8 `json:"digestType" happydns:"label=Digest Type"`
Digest string `json:"digest" happydns:"label=Digest"`
}
type Delegation struct {
NameServers []string `json:"ns" happydns:"label=Name Servers"`
DS []DS `json:"ds" happydns:"label=Delegation Signer"`
NameServers []string `json:"ns" happydns:"label=Name Servers"`
DS []svcs.DS `json:"ds" happydns:"label=Delegation Signer"`
}
func (s *Delegation) GetNbResources() int {
@ -94,10 +88,10 @@ func (s *Delegation) GenRRs(domain string, ttl uint32, origin string) (rrs []dns
return
}
func delegation_analyze(a *Analyzer) error {
func delegation_analyze(a *svcs.Analyzer) error {
delegations := map[string]*Delegation{}
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeNS}) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeNS}) {
if ns, ok := record.(*dns.NS); ok {
if _, ok := delegations[ns.Header().Name]; !ok {
delegations[ns.Header().Name] = &Delegation{}
@ -114,9 +108,9 @@ func delegation_analyze(a *Analyzer) error {
}
for subdomain := range delegations {
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeDS, Domain: subdomain}) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeDS, Domain: subdomain}) {
if ds, ok := record.(*dns.DS); ok {
delegations[subdomain].DS = append(delegations[subdomain].DS, DS{
delegations[subdomain].DS = append(delegations[subdomain].DS, svcs.DS{
KeyTag: ds.KeyTag,
Algorithm: ds.Algorithm,
DigestType: ds.DigestType,
@ -136,18 +130,19 @@ func delegation_analyze(a *Analyzer) error {
}
func init() {
RegisterService(
svcs.RegisterService(
func() happydns.Service {
return &Delegation{}
},
delegation_analyze,
ServiceInfos{
svcs.ServiceInfos{
Name: "Delegation",
Description: "Delegate this subdomain to another name server",
Family: svcs.Abstract,
Categories: []string{
"internal",
},
Restrictions: ServiceRestrictions{
Restrictions: svcs.ServiceRestrictions{
Alone: true,
Leaf: true,
ExclusiveRR: []string{"svcs.Origin"},

View File

@ -29,7 +29,7 @@
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
package abstract
import (
"bytes"
@ -39,79 +39,17 @@ import (
"github.com/miekg/dns"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/services"
"git.happydns.org/happydns/utils"
)
type MX struct {
Target string `json:"target"`
Preference uint16 `json:"preference,omitempty"`
}
type SPFDirective struct {
Qualifier byte
Mechanism string
}
type SPFModifier struct {
Name string
Mechanism string
}
type SPFExplanation struct {
DomainSpec string
}
type SPFRedirect struct {
DomainSpec string
}
type SPF struct {
Content string
}
func (t *SPF) String() string {
return t.Content
}
type DKIM struct {
Fields []string
}
func (t *DKIM) String() string {
return strings.Join(t.Fields, "; ")
}
type DMARC struct {
Fields []string
}
func (t *DMARC) String() string {
return strings.Join(t.Fields, ";")
}
type MTA_STS struct {
Fields []string
}
func (t *MTA_STS) String() string {
return strings.Join(t.Fields, ";")
}
type TLS_RPT struct {
Fields []string
}
func (t *TLS_RPT) String() string {
return strings.Join(t.Fields, ";")
}
type EMail struct {
MX []MX `json:"mx,omitempty" happydns:"label=EMail Servers"`
SPF *SPF `json:"spf,omitempty" happydns:"label=Sender Policy Framework"`
DKIM map[string]*DKIM `json:"dkim,omitempty" happydns:"label=Domain Keys"`
DMARC *DMARC `json:"dmarc,omitempty" happydns:"label=DMARC"`
MTA_STS *MTA_STS `json:"mta_sts,omitempty" happydns:"label=Strict Transport Security"`
TLS_RPT *TLS_RPT `json:"tls_rpt,omitempty" happydns:"label=TLS Reporting"`
MX []svcs.MX `json:"mx,omitempty" happydns:"label=EMail Servers"`
SPF *svcs.SPF `json:"spf,omitempty" happydns:"label=Sender Policy Framework"`
DKIM map[string]*svcs.DKIM `json:"dkim,omitempty" happydns:"label=Domain Keys"`
DMARC *svcs.DMARC `json:"dmarc,omitempty" happydns:"label=DMARC"`
MTA_STS *svcs.MTA_STS `json:"mta_sts,omitempty" happydns:"label=Strict Transport Security"`
TLS_RPT *svcs.TLS_RPT `json:"tls_rpt,omitempty" happydns:"label=TLS Reporting"`
}
func (s *EMail) GetNbResources() int {
@ -253,11 +191,11 @@ func (s *EMail) GenRRs(domain string, ttl uint32, origin string) (rrs []dns.RR)
return
}
func email_analyze(a *Analyzer) (err error) {
func email_analyze(a *svcs.Analyzer) (err error) {
services := map[string]*EMail{}
// Handle only MX records
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeMX}) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeMX}) {
if mx, ok := record.(*dns.MX); ok {
dn := mx.Header().Name
@ -267,7 +205,7 @@ func email_analyze(a *Analyzer) (err error) {
services[dn].MX = append(
services[dn].MX,
MX{
svcs.MX{
Target: mx.Mx,
Preference: mx.Preference,
},
@ -286,9 +224,9 @@ func email_analyze(a *Analyzer) (err error) {
for domain, service := range services {
// Is there SPF record?
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeTXT, Domain: domain, Contains: "v=spf1"}) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeTXT, Domain: domain, Contains: "v=spf1"}) {
if service.SPF == nil {
service.SPF = &SPF{}
service.SPF = &svcs.SPF{}
}
if txt, ok := record.(*dns.TXT); ok {
@ -312,13 +250,13 @@ func email_analyze(a *Analyzer) (err error) {
}
}
service.DKIM = map[string]*DKIM{}
service.DKIM = map[string]*svcs.DKIM{}
// Is there DKIM record?
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeTXT, SubdomainsOf: "_domainkey." + domain}) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeTXT, SubdomainsOf: "_domainkey." + domain}) {
selector := strings.TrimSuffix(record.Header().Name, "._domainkey."+domain)
if _, ok := service.DKIM[selector]; !ok {
service.DKIM[selector] = &DKIM{}
service.DKIM[selector] = &svcs.DKIM{}
}
if txt, ok := record.(*dns.TXT); ok {
@ -332,9 +270,9 @@ func email_analyze(a *Analyzer) (err error) {
}
// Is there DMARC record?
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeTXT, Domain: "_dmarc." + domain}) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeTXT, Domain: "_dmarc." + domain}) {
if service.DMARC == nil {
service.DMARC = &DMARC{}
service.DMARC = &svcs.DMARC{}
}
if txt, ok := record.(*dns.TXT); ok {
@ -348,9 +286,9 @@ func email_analyze(a *Analyzer) (err error) {
}
// Is there MTA-STS record?
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeTXT, Domain: "_mta-sts." + domain}) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeTXT, Domain: "_mta-sts." + domain}) {
if service.MTA_STS == nil {
service.MTA_STS = &MTA_STS{}
service.MTA_STS = &svcs.MTA_STS{}
}
if txt, ok := record.(*dns.TXT); ok {
@ -364,9 +302,9 @@ func email_analyze(a *Analyzer) (err error) {
}
// Is there MTA-STS record?
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeTXT, Domain: "_smtp._tls." + domain}) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeTXT, Domain: "_smtp._tls." + domain}) {
if service.TLS_RPT == nil {
service.TLS_RPT = &TLS_RPT{}
service.TLS_RPT = &svcs.TLS_RPT{}
}
if txt, ok := record.(*dns.TXT); ok {
@ -384,19 +322,20 @@ func email_analyze(a *Analyzer) (err error) {
}
func init() {
RegisterService(
svcs.RegisterService(
func() happydns.Service {
return &EMail{}
},
email_analyze,
ServiceInfos{
svcs.ServiceInfos{
Name: "E-Mail",
Description: "Send and receive e-mail with this domain.",
Family: svcs.Abstract,
Categories: []string{
"email",
},
Tabs: true,
Restrictions: ServiceRestrictions{
Restrictions: svcs.ServiceRestrictions{
Single: true,
NeedTypes: []uint16{
dns.TypeMX,

View File

@ -29,7 +29,7 @@
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
package abstract
import (
"bytes"
@ -39,11 +39,12 @@ import (
"github.com/miekg/dns"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/services"
"git.happydns.org/happydns/utils"
)
type MatrixIM struct {
Matrix []*SRV `json:"matrix"`
Matrix []*svcs.SRV `json:"matrix"`
}
func (s *MatrixIM) GetNbResources() int {
@ -96,11 +97,11 @@ func (s *MatrixIM) GenRRs(domain string, ttl uint32, origin string) (rrs []dns.R
return
}
func matrix_analyze(a *Analyzer) error {
func matrix_analyze(a *svcs.Analyzer) error {
matrixDomains := map[string]*MatrixIM{}
for _, record := range a.SearchRR(AnalyzerRecordFilter{Prefix: "_matrix._tcp.", Type: dns.TypeSRV}) {
if srv := parseSRV(record); srv != nil {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Prefix: "_matrix._tcp.", Type: dns.TypeSRV}) {
if srv := svcs.ParseSRV(record); srv != nil {
domain := strings.TrimPrefix(record.Header().Name, "_matrix._tcp.")
if _, ok := matrixDomains[domain]; !ok {
@ -120,18 +121,19 @@ func matrix_analyze(a *Analyzer) error {
}
func init() {
RegisterService(
svcs.RegisterService(
func() happydns.Service {
return &MatrixIM{}
},
matrix_analyze,
ServiceInfos{
svcs.ServiceInfos{
Name: "Matrix IM",
Description: "Communicate on Matrix using your domain.",
Family: svcs.Abstract,
Categories: []string{
"im",
},
Restrictions: ServiceRestrictions{
Restrictions: svcs.ServiceRestrictions{
NearAlone: true,
Single: true,
NeedTypes: []uint16{

View File

@ -29,7 +29,7 @@
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
package abstract
import (
"crypto/sha256"
@ -41,6 +41,7 @@ import (
"github.com/miekg/dns"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/services"
"git.happydns.org/happydns/utils"
)
@ -116,8 +117,8 @@ func (s *SMimeCert) GenRRs(domain string, ttl uint32, origin string) (rrs []dns.
return
}
func openpgpkey_analyze(a *Analyzer) (err error) {
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeOPENPGPKEY, Contains: "._openpgpkey."}) {
func openpgpkey_analyze(a *svcs.Analyzer) (err error) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeOPENPGPKEY, Contains: "._openpgpkey."}) {
if openpgpkey, ok := record.(*dns.OPENPGPKEY); ok {
domain := record.Header().Name
domain = domain[strings.Index(domain, "._openpgpkey")+13:]
@ -146,8 +147,8 @@ func openpgpkey_analyze(a *Analyzer) (err error) {
return
}
func smimea_analyze(a *Analyzer) (err error) {
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeSMIMEA, Contains: "._smimecert."}) {
func smimea_analyze(a *svcs.Analyzer) (err error) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeSMIMEA, Contains: "._smimecert."}) {
if smimecert, ok := record.(*dns.SMIMEA); ok {
domain := record.Header().Name
domain = domain[strings.Index(domain, "._smimecert")+12:]
@ -181,18 +182,19 @@ func smimea_analyze(a *Analyzer) (err error) {
}
func init() {
RegisterService(
svcs.RegisterService(
func() happydns.Service {
return &OpenPGP{}
},
openpgpkey_analyze,
ServiceInfos{
svcs.ServiceInfos{
Name: "PGP Key",
Description: "Let users retrieve PGP key automatically.",
Family: svcs.Abstract,
Categories: []string{
"email",
},
Restrictions: ServiceRestrictions{
Restrictions: svcs.ServiceRestrictions{
NearAlone: true,
NeedTypes: []uint16{
dns.TypeOPENPGPKEY,
@ -201,18 +203,19 @@ func init() {
},
1,
)
RegisterService(
svcs.RegisterService(
func() happydns.Service {
return &SMimeCert{}
},
smimea_analyze,
ServiceInfos{
svcs.ServiceInfos{
Name: "SMimeCert",
Description: "Publish S/MIME certificate.",
Family: svcs.Abstract,
Categories: []string{
"email",
},
Restrictions: ServiceRestrictions{
Restrictions: svcs.ServiceRestrictions{
NearAlone: true,
NeedTypes: []uint16{
dns.TypeSMIMEA,

View File

@ -29,7 +29,7 @@
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
package abstract
import (
"fmt"
@ -39,6 +39,7 @@ import (
"github.com/miekg/dns"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/services"
"git.happydns.org/happydns/utils"
)
@ -96,8 +97,8 @@ func (s *Origin) GenRRs(domain string, ttl uint32, origin string) (rrs []dns.RR)
return
}
func origin_analyze(a *Analyzer) error {
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeSOA}) {
func origin_analyze(a *svcs.Analyzer) error {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeSOA}) {
if soa, ok := record.(*dns.SOA); ok {
origin := &Origin{
Ns: soa.Ns,
@ -115,7 +116,7 @@ func origin_analyze(a *Analyzer) error {
origin,
)
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeNS, Domain: soa.Header().Name}) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeNS, Domain: soa.Header().Name}) {
if ns, ok := record.(*dns.NS); ok {
origin.NameServers = append(origin.NameServers, ns.Ns)
a.UseRR(
@ -131,18 +132,19 @@ func origin_analyze(a *Analyzer) error {
}
func init() {
RegisterService(
svcs.RegisterService(
func() happydns.Service {
return &Origin{}
},
origin_analyze,
ServiceInfos{
svcs.ServiceInfos{
Name: "Origin",
Description: "This is the root of your domain.",
Family: svcs.Abstract,
Categories: []string{
"internal",
},
Restrictions: ServiceRestrictions{
Restrictions: svcs.ServiceRestrictions{
RootOnly: true,
Single: true,
NeedTypes: []uint16{

View File

@ -29,7 +29,7 @@
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
package abstract
import (
"bytes"
@ -39,19 +39,14 @@ import (
"github.com/miekg/dns"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/services"
"git.happydns.org/happydns/utils"
)
type SSHFP struct {
Algorithm uint8 `json:"algorithm"`
Type uint8 `json:"type"`
FingerPrint string `json:"fingerprint"`
}
type Server struct {
A *net.IP `json:"A,omitempty" happydns:"label=ipv4,description=Server's IPv4"`
AAAA *net.IP `json:"AAAA,omitempty" happydns:"label=ipv6,description=Server's IPv6"`
SSHFP []*SSHFP `json:"SSHFP,omitempty" happydns:"label=SSH Fingerprint,description=Server's SSH fingerprint"`
A *net.IP `json:"A,omitempty" happydns:"label=ipv4,description=Server's IPv4"`
AAAA *net.IP `json:"AAAA,omitempty" happydns:"label=ipv6,description=Server's IPv6"`
SSHFP []*svcs.SSHFP `json:"SSHFP,omitempty" happydns:"label=SSH Fingerprint,description=Server's SSH fingerprint"`
}
func (s *Server) GetNbResources() int {
@ -119,10 +114,10 @@ func (s *Server) GenRRs(domain string, ttl uint32, origin string) (rrs []dns.RR)
return
}
func server_analyze(a *Analyzer) error {
func server_analyze(a *svcs.Analyzer) error {
pool := map[string][]dns.RR{}
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeA}, AnalyzerRecordFilter{Type: dns.TypeAAAA}, AnalyzerRecordFilter{Type: dns.TypeSSHFP}) {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeA}, svcs.AnalyzerRecordFilter{Type: dns.TypeAAAA}, svcs.AnalyzerRecordFilter{Type: dns.TypeSSHFP}) {
domain := record.Header().Name
pool[domain] = append(pool[domain], record)
@ -147,7 +142,7 @@ next_pool:
s.AAAA = &rr.(*dns.AAAA).AAAA
} else if rr.Header().Rrtype == dns.TypeSSHFP {
sshfp := rr.(*dns.SSHFP)
s.SSHFP = append(s.SSHFP, &SSHFP{
s.SSHFP = append(s.SSHFP, &svcs.SSHFP{
Algorithm: sshfp.Algorithm,
Type: sshfp.Type,
FingerPrint: sshfp.FingerPrint,
@ -164,18 +159,19 @@ next_pool:
}
func init() {
RegisterService(
svcs.RegisterService(
func() happydns.Service {
return &Server{}
},
server_analyze,
ServiceInfos{
svcs.ServiceInfos{
Name: "Server",
Description: "A computer will respond to some requests.",
Family: svcs.Abstract,
Categories: []string{
"server",
},
Restrictions: ServiceRestrictions{
Restrictions: svcs.ServiceRestrictions{
GLUE: true,
},
},

View File

@ -29,7 +29,7 @@
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
package abstract
import (
"bytes"
@ -40,13 +40,14 @@ import (
"github.com/miekg/dns"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/services"
"git.happydns.org/happydns/utils"
)
type XMPP struct {
Client []*SRV `json:"client,omitempty" happydns:"label=Client Connection"`
Server []*SRV `json:"server,omitempty" happydns:"label=Server Connection"`
Jabber []*SRV `json:"jabber,omitempty" happydns:"label=Jabber Connection (legacy)"`
Client []*svcs.SRV `json:"client,omitempty" happydns:"label=Client Connection"`
Server []*svcs.SRV `json:"server,omitempty" happydns:"label=Server Connection"`
Jabber []*svcs.SRV `json:"jabber,omitempty" happydns:"label=Jabber Connection (legacy)"`
}
func (s *XMPP) GetNbResources() (max int) {
@ -112,9 +113,9 @@ func (s *XMPP) GenRRs(domain string, ttl uint32, origin string) (rrs []dns.RR) {
return
}
func xmpp_subanalyze(a *Analyzer, prefix string, xmppDomains map[string]*XMPP, field string) error {
for _, record := range a.SearchRR(AnalyzerRecordFilter{Prefix: prefix, Type: dns.TypeSRV}) {
if srv := parseSRV(record); srv != nil {
func xmpp_subanalyze(a *svcs.Analyzer, prefix string, xmppDomains map[string]*XMPP, field string) error {
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Prefix: prefix, Type: dns.TypeSRV}) {
if srv := svcs.ParseSRV(record); srv != nil {
domain := strings.TrimPrefix(record.Header().Name, prefix)
if _, ok := xmppDomains[domain]; !ok {
@ -135,7 +136,7 @@ func xmpp_subanalyze(a *Analyzer, prefix string, xmppDomains map[string]*XMPP, f
return nil
}
func xmpp_analyze(a *Analyzer) error {
func xmpp_analyze(a *svcs.Analyzer) error {
xmppDomains := map[string]*XMPP{}
xmpp_subanalyze(a, "_jabber._tcp.", xmppDomains, "Jabber")
@ -146,18 +147,19 @@ func xmpp_analyze(a *Analyzer) error {
}
func init() {
RegisterService(
svcs.RegisterService(
func() happydns.Service {
return &XMPP{}
},
xmpp_analyze,
ServiceInfos{
svcs.ServiceInfos{
Name: "XMPP IM",
Description: "Communicate over XMPP with your domain.",
Family: svcs.Abstract,
Categories: []string{
"im",
},
Restrictions: ServiceRestrictions{
Restrictions: svcs.ServiceRestrictions{
NearAlone: true,
Single: true,
NeedTypes: []uint16{

View File

@ -36,10 +36,16 @@ import (
"log"
"reflect"
"sort"
"strings"
"git.happydns.org/happydns/model"
)
const (
Abstract = "abstract"
Provider = "provider"
)
type ServiceCreator func() happydns.Service
type SubServiceCreator func() interface{}
type ServiceAnalyzer func(*Analyzer) error
@ -90,7 +96,7 @@ func RegisterService(creator ServiceCreator, analyzer ServiceAnalyzer, infos Ser
}
func RegisterSubServices(t reflect.Type) {
if t.Kind() == reflect.Struct && t.PkgPath() == pathToSvcsModule {
if t.Kind() == reflect.Struct && strings.HasPrefix(t.PkgPath(), pathToSvcsModule) {
if _, ok := subServices[t.String()]; !ok {
log.Println("Registering new subservice:", t.String())
@ -138,7 +144,7 @@ func GetServices() *map[string]*Svc {
func FindService(name string) (happydns.Service, error) {
svc, ok := services[name]
if !ok {
return nil, fmt.Errorf("Unable to find corresponding service for `%s`.", name)
return nil, ServiceNotFoundError{name}
}
return svc.Creator(), nil

44
services/dkim.go Normal file
View File

@ -0,0 +1,44 @@
// Copyright or © or Copr. happyDNS (2020)
//
// contact@happydns.org
//
// This software is a computer program whose purpose is to provide a modern
// interface to interact with DNS systems.
//
// This software is governed by the CeCILL license under French law and abiding
// by the rules of distribution of free software. You can use, modify and/or
// redistribute the software under the terms of the CeCILL license as
// circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info".
//
// As a counterpart to the access to the source code and rights to copy, modify
// and redistribute granted by the license, users are provided only with a
// limited warranty and the software's author, the holder of the economic
// rights, and the successive licensors have only limited liability.
//
// In this respect, the user's attention is drawn to the risks associated with
// loading, using, modifying and/or developing or reproducing the software by
// the user in light of its specific status of free software, that may mean
// that it is complicated to manipulate, and that also therefore means that it
// is reserved for developers and experienced professionals having in-depth
// computer knowledge. Users are therefore encouraged to load and test the
// software's suitability as regards their requirements in conditions enabling
// the security of their systems and/or data to be ensured and, more generally,
// to use and operate it in the same conditions as regards security.
//
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
import (
"strings"
)
type DKIM struct {
Fields []string
}
func (t *DKIM) String() string {
return strings.Join(t.Fields, "; ")
}

44
services/dmarc.go Normal file
View File

@ -0,0 +1,44 @@
// Copyright or © or Copr. happyDNS (2020)
//
// contact@happydns.org
//
// This software is a computer program whose purpose is to provide a modern
// interface to interact with DNS systems.
//
// This software is governed by the CeCILL license under French law and abiding
// by the rules of distribution of free software. You can use, modify and/or
// redistribute the software under the terms of the CeCILL license as
// circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info".
//
// As a counterpart to the access to the source code and rights to copy, modify
// and redistribute granted by the license, users are provided only with a
// limited warranty and the software's author, the holder of the economic
// rights, and the successive licensors have only limited liability.
//
// In this respect, the user's attention is drawn to the risks associated with
// loading, using, modifying and/or developing or reproducing the software by
// the user in light of its specific status of free software, that may mean
// that it is complicated to manipulate, and that also therefore means that it
// is reserved for developers and experienced professionals having in-depth
// computer knowledge. Users are therefore encouraged to load and test the
// software's suitability as regards their requirements in conditions enabling
// the security of their systems and/or data to be ensured and, more generally,
// to use and operate it in the same conditions as regards security.
//
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
import (
"strings"
)
type DMARC struct {
Fields []string
}
func (t *DMARC) String() string {
return strings.Join(t.Fields, ";")
}

41
services/ds.go Normal file
View File

@ -0,0 +1,41 @@
// Copyright or © or Copr. happyDNS (2020)
//
// contact@happydns.org
//
// This software is a computer program whose purpose is to provide a modern
// interface to interact with DNS systems.
//
// This software is governed by the CeCILL license under French law and abiding
// by the rules of distribution of free software. You can use, modify and/or
// redistribute the software under the terms of the CeCILL license as
// circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info".
//
// As a counterpart to the access to the source code and rights to copy, modify
// and redistribute granted by the license, users are provided only with a
// limited warranty and the software's author, the holder of the economic
// rights, and the successive licensors have only limited liability.
//
// In this respect, the user's attention is drawn to the risks associated with
// loading, using, modifying and/or developing or reproducing the software by
// the user in light of its specific status of free software, that may mean
// that it is complicated to manipulate, and that also therefore means that it
// is reserved for developers and experienced professionals having in-depth
// computer knowledge. Users are therefore encouraged to load and test the
// software's suitability as regards their requirements in conditions enabling
// the security of their systems and/or data to be ensured and, more generally,
// to use and operate it in the same conditions as regards security.
//
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
import ()
type DS struct {
KeyTag uint16 `json:"keytag" happydns:"label=Key Tag"`
Algorithm uint8 `json:"algorithm" happydns:"label=Algorithm"`
DigestType uint8 `json:"digestType" happydns:"label=Digest Type"`
Digest string `json:"digest" happydns:"label=Digest"`
}

View File

@ -33,6 +33,7 @@ package svcs
import (
"encoding/json"
"fmt"
"git.happydns.org/happydns/model"
)
@ -66,6 +67,7 @@ type ServiceRestrictions struct {
type ServiceInfos struct {
Name string `json:"name"`
Description string `json:"description"`
Family string `json:"family"`
Categories []string `json:"categories"`
Tabs bool `json:"tabs,omitempty"`
Restrictions ServiceRestrictions `json:"restrictions,omitempty"`
@ -75,6 +77,14 @@ type serviceCombined struct {
Service happydns.Service
}
type ServiceNotFoundError struct {
name string
}
func (err ServiceNotFoundError) Error() string {
return fmt.Sprintf("Unable to find corresponding service for `%s`.", err.name)
}
// UnmarshalServiceJSON implements the UnmarshalJSON function for the
// encoding/json module.
func UnmarshalServiceJSON(svc *happydns.ServiceCombined, b []byte) (err error) {
@ -86,6 +96,9 @@ func UnmarshalServiceJSON(svc *happydns.ServiceCombined, b []byte) (err error) {
var tsvc happydns.Service
tsvc, err = FindService(svcType.Type)
if err != nil {
return
}
mySvc := &serviceCombined{
tsvc,

44
services/mta-sts.go Normal file
View File

@ -0,0 +1,44 @@
// Copyright or © or Copr. happyDNS (2020)
//
// contact@happydns.org
//
// This software is a computer program whose purpose is to provide a modern
// interface to interact with DNS systems.
//
// This software is governed by the CeCILL license under French law and abiding
// by the rules of distribution of free software. You can use, modify and/or
// redistribute the software under the terms of the CeCILL license as
// circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info".
//
// As a counterpart to the access to the source code and rights to copy, modify
// and redistribute granted by the license, users are provided only with a
// limited warranty and the software's author, the holder of the economic
// rights, and the successive licensors have only limited liability.
//
// In this respect, the user's attention is drawn to the risks associated with
// loading, using, modifying and/or developing or reproducing the software by
// the user in light of its specific status of free software, that may mean
// that it is complicated to manipulate, and that also therefore means that it
// is reserved for developers and experienced professionals having in-depth
// computer knowledge. Users are therefore encouraged to load and test the
// software's suitability as regards their requirements in conditions enabling
// the security of their systems and/or data to be ensured and, more generally,
// to use and operate it in the same conditions as regards security.
//
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
import (
"strings"
)
type MTA_STS struct {
Fields []string
}
func (t *MTA_STS) String() string {
return strings.Join(t.Fields, ";")
}

39
services/mx.go Normal file
View File

@ -0,0 +1,39 @@
// Copyright or © or Copr. happyDNS (2020)
//
// contact@happydns.org
//
// This software is a computer program whose purpose is to provide a modern
// interface to interact with DNS systems.
//
// This software is governed by the CeCILL license under French law and abiding
// by the rules of distribution of free software. You can use, modify and/or
// redistribute the software under the terms of the CeCILL license as
// circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info".
//
// As a counterpart to the access to the source code and rights to copy, modify
// and redistribute granted by the license, users are provided only with a
// limited warranty and the software's author, the holder of the economic
// rights, and the successive licensors have only limited liability.
//
// In this respect, the user's attention is drawn to the risks associated with
// loading, using, modifying and/or developing or reproducing the software by
// the user in light of its specific status of free software, that may mean
// that it is complicated to manipulate, and that also therefore means that it
// is reserved for developers and experienced professionals having in-depth
// computer knowledge. Users are therefore encouraged to load and test the
// software's suitability as regards their requirements in conditions enabling
// the security of their systems and/or data to be ensured and, more generally,
// to use and operate it in the same conditions as regards security.
//
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
import ()
type MX struct {
Target string `json:"target"`
Preference uint16 `json:"preference,omitempty"`
}

View File

@ -0,0 +1,119 @@
// Copyright or © or Copr. happyDNS (2020)
//
// contact@happydns.org
//
// This software is a computer program whose purpose is to provide a modern
// interface to interact with DNS systems.
//
// This software is governed by the CeCILL license under French law and abiding
// by the rules of distribution of free software. You can use, modify and/or
// redistribute the software under the terms of the CeCILL license as
// circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info".
//
// As a counterpart to the access to the source code and rights to copy, modify
// and redistribute granted by the license, users are provided only with a
// limited warranty and the software's author, the holder of the economic
// rights, and the successive licensors have only limited liability.
//
// In this respect, the user's attention is drawn to the risks associated with
// loading, using, modifying and/or developing or reproducing the software by
// the user in light of its specific status of free software, that may mean
// that it is complicated to manipulate, and that also therefore means that it
// is reserved for developers and experienced professionals having in-depth
// computer knowledge. Users are therefore encouraged to load and test the
// software's suitability as regards their requirements in conditions enabling
// the security of their systems and/or data to be ensured and, more generally,
// to use and operate it in the same conditions as regards security.
//
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package google // import "happydns.org/services/providers/google"
import (
"strings"
"github.com/miekg/dns"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/services"
"git.happydns.org/happydns/services/abstract"
)
type GSuite struct {
ValidationCode string `json:"validationCode,omitempty" happydns:"label=Validation Code,placeholder=abcdef0123.mx-verification.google.com.,description=The verification code will be displayed during the initial domain setup and will not be usefull after Google validation."`
}
func (s *GSuite) GenKnownSvcs() []happydns.Service {
knownSvc := &abstract.EMail{
MX: []svcs.MX{
svcs.MX{Target: "ASPMX.L.GOOGLE.COM.", Preference: 1},
svcs.MX{Target: "ALT1.ASPMX.L.GOOGLE.COM.", Preference: 5},
svcs.MX{Target: "ALT2.ASPMX.L.GOOGLE.COM.", Preference: 5},
svcs.MX{Target: "ALT3.ASPMX.L.GOOGLE.COM.", Preference: 10},
svcs.MX{Target: "ALT4.ASPMX.L.GOOGLE.COM.", Preference: 10},
},
}
if len(s.ValidationCode) > 0 {
knownSvc.MX = append(knownSvc.MX, svcs.MX{
Target: s.ValidationCode,
Preference: 15,
})
}
return []happydns.Service{knownSvc}
}
func (s *GSuite) GetNbResources() int {
return 1
}
func (s *GSuite) GenComment(origin string) string {
var comments []string
for _, svc := range s.GenKnownSvcs() {
comments = append(comments, svc.GenComment(origin))
}
return strings.Join(comments, ", ")
}
func (s *GSuite) GenRRs(domain string, ttl uint32, origin string) (rrs []dns.RR) {
for _, svc := range s.GenKnownSvcs() {
rrs = append(rrs, svc.GenRRs(domain, ttl, origin)...)
}
return
}
func gsuite_analyze(a *svcs.Analyzer) error {
return nil
}
func init() {
svcs.RegisterService(
func() happydns.Service {
return &GSuite{}
},
gsuite_analyze,
svcs.ServiceInfos{
Name: "G Suite",
Description: "The suite of cloud computing, productivity and collaboration tools by Google.",
Family: svcs.Provider,
Categories: []string{
"cloud",
"email",
},
Restrictions: svcs.ServiceRestrictions{
ExclusiveRR: []string{
"abstract.EMail",
"svcs.MX",
},
Single: true,
NeedTypes: []uint16{
dns.TypeMX,
},
},
},
0,
)
}

60
services/spf.go Normal file
View File

@ -0,0 +1,60 @@
// Copyright or © or Copr. happyDNS (2020)
//
// contact@happydns.org
//
// This software is a computer program whose purpose is to provide a modern
// interface to interact with DNS systems.
//
// This software is governed by the CeCILL license under French law and abiding
// by the rules of distribution of free software. You can use, modify and/or
// redistribute the software under the terms of the CeCILL license as
// circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info".
//
// As a counterpart to the access to the source code and rights to copy, modify
// and redistribute granted by the license, users are provided only with a
// limited warranty and the software's author, the holder of the economic
// rights, and the successive licensors have only limited liability.
//
// In this respect, the user's attention is drawn to the risks associated with
// loading, using, modifying and/or developing or reproducing the software by
// the user in light of its specific status of free software, that may mean
// that it is complicated to manipulate, and that also therefore means that it
// is reserved for developers and experienced professionals having in-depth
// computer knowledge. Users are therefore encouraged to load and test the
// software's suitability as regards their requirements in conditions enabling
// the security of their systems and/or data to be ensured and, more generally,
// to use and operate it in the same conditions as regards security.
//
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
import ()
type SPFDirective struct {
Qualifier byte
Mechanism string
}
type SPFModifier struct {
Name string
Mechanism string
}
type SPFExplanation struct {
DomainSpec string
}
type SPFRedirect struct {
DomainSpec string
}
type SPF struct {
Content string
}
func (t *SPF) String() string {
return t.Content
}

View File

@ -73,7 +73,7 @@ func (s *SRV) GenRRs(domain string, ttl uint32, origin string) (rrs []dns.RR) {
return
}
func parseSRV(record dns.RR) (ret *SRV) {
func ParseSRV(record dns.RR) (ret *SRV) {
if srv, ok := record.(*dns.SRV); ok {
ret = &SRV{
Priority: srv.Priority,
@ -116,7 +116,7 @@ func srv_analyze(a *Analyzer) error {
for _, record := range a.SearchRR(AnalyzerRecordFilter{Type: dns.TypeSRV}) {
subdomains := SRV_DOMAIN.FindStringSubmatch(record.Header().Name)
if srv := parseSRV(record); len(subdomains) == 4 && srv != nil {
if srv := ParseSRV(record); len(subdomains) == 4 && srv != nil {
svc := subdomains[1] + "." + subdomains[2]
domain := subdomains[3]

40
services/sshfp.go Normal file
View File

@ -0,0 +1,40 @@
// Copyright or © or Copr. happyDNS (2020)
//
// contact@happydns.org
//
// This software is a computer program whose purpose is to provide a modern
// interface to interact with DNS systems.
//
// This software is governed by the CeCILL license under French law and abiding
// by the rules of distribution of free software. You can use, modify and/or
// redistribute the software under the terms of the CeCILL license as
// circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info".
//
// As a counterpart to the access to the source code and rights to copy, modify
// and redistribute granted by the license, users are provided only with a
// limited warranty and the software's author, the holder of the economic
// rights, and the successive licensors have only limited liability.
//
// In this respect, the user's attention is drawn to the risks associated with
// loading, using, modifying and/or developing or reproducing the software by
// the user in light of its specific status of free software, that may mean
// that it is complicated to manipulate, and that also therefore means that it
// is reserved for developers and experienced professionals having in-depth
// computer knowledge. Users are therefore encouraged to load and test the
// software's suitability as regards their requirements in conditions enabling
// the security of their systems and/or data to be ensured and, more generally,
// to use and operate it in the same conditions as regards security.
//
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
import ()
type SSHFP struct {
Algorithm uint8 `json:"algorithm"`
Type uint8 `json:"type"`
FingerPrint string `json:"fingerprint"`
}

44
services/tls-rpt.go Normal file
View File

@ -0,0 +1,44 @@
// Copyright or © or Copr. happyDNS (2020)
//
// contact@happydns.org
//
// This software is a computer program whose purpose is to provide a modern
// interface to interact with DNS systems.
//
// This software is governed by the CeCILL license under French law and abiding
// by the rules of distribution of free software. You can use, modify and/or
// redistribute the software under the terms of the CeCILL license as
// circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info".
//
// As a counterpart to the access to the source code and rights to copy, modify
// and redistribute granted by the license, users are provided only with a
// limited warranty and the software's author, the holder of the economic
// rights, and the successive licensors have only limited liability.
//
// In this respect, the user's attention is drawn to the risks associated with
// loading, using, modifying and/or developing or reproducing the software by
// the user in light of its specific status of free software, that may mean
// that it is complicated to manipulate, and that also therefore means that it
// is reserved for developers and experienced professionals having in-depth
// computer knowledge. Users are therefore encouraged to load and test the
// software's suitability as regards their requirements in conditions enabling
// the security of their systems and/or data to be ensured and, more generally,
// to use and operate it in the same conditions as regards security.
//
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package svcs
import (
"strings"
)
type TLS_RPT struct {
Fields []string
}
func (t *TLS_RPT) String() string {
return strings.Join(t.Fields, ";")
}