Пример #1
0
// Recursively takes an spf record and resolves into a list of IP addresses
//TODO: Handle IPv6 addresses. Currently ignoring due to the huge
//		performance hit. Too slow.
func TraverseSPF(records []string) string {
	var expandedSPF string
	var recordArr []string

	for _, record := range records {
		// Skip non SPF TXT records
		if !strings.Contains(record, "spf") {
			continue
		}

		//fmt.Printf("\nExpanding \"%s\"", record)

		// Explode record on spaces
		recordArr = strings.Split(record, " ")
		//fmt.Printf("\nSplit \"%q\"", recordArr)

		// Loop through all directives and process
		for _, r := range recordArr {
			// Lines start with - are fails
			if strings.HasPrefix(r, "-") {
				continue
			}
			// Get TXT records and for each include
			if strings.Contains(r, "include:") {
				temp := strings.Replace(strings.Replace(strings.Replace(r, "+include:", "", -1), "~include:", "", -1), "include:", "", -1)
				passArr, _ := net.LookupTXT(temp)
				//fmt.Printf("\n	Found include")
				expandedSPF = expandedSPF + " " + TraverseSPF(passArr)
				// Expand redirects
			} else if strings.Contains(r, "redirect=") {
				passArr, _ := net.LookupTXT(strings.Replace(r, "redirect=", "", -1))
				//fmt.Printf("\n	Found redirect")
				expandedSPF = expandedSPF + " " + TraverseSPF(passArr)
				// If contains mx get mx records
			} else if strings.Contains(r, "mx:") {
				//TODO: Add MX expansion
				// Currently this is just ignoring mx records as if they were invalid
				//passArr, _ := net.LookupMX(strings.Replace(r, "mx:", "", -1))
				//fmt.Printf("\n	Found mx")
				//expandedSPF = expandedSPF + " " + TraverseSPF(passArr)
			} else {
				//fmt.Printf("\n	Nothing to expand")
				expandedSPF = expandedSPF + " " + r
			}
		}
	}

	return expandedSPF
}
Пример #2
0
func main() {
	txt, err := net.LookupTXT("rs.dns-oarc.net")
	if err != nil {
		fmt.Println(err)
	}
	fmt.Printf("%v", txt)
}
Пример #3
0
func (rbl *RBL) LookupRBL(ip net.IP) (RBLResult, error) {
	res := RBLResult{
		Listed: false,
		Ip:     ip,
		Zone:   rbl.Zone,
		Text:   "",
	}

	query, err := rbl.query(ip)
	if err != nil {
		return res, err
	}

	addrs, err := net.LookupHost(query)
	reg, _ := regexp.Compile("(?i:no such host)")
	if err != nil && reg.FindStringIndex(err.Error()) == nil {
		return res, err
	}

	if len(addrs) > 0 {
		res.Listed = true
		text, err := net.LookupTXT(query)
		if err == nil {
			res.Text = strings.Join(text, "\n")
		}
	}

	return res, nil
}
func runTraceroute(targetHost string, ipChan chan []string, waitChan chan int) {
	app := "traceroute"
	arg0 := "-f" //-f 2
	arg1 := "1"  //first ttl
	arg2 := "-m"
	arg3 := "25" //max ttl
	arg4 := "-q"
	arg5 := "3" //number of tries per hop
	arg6 := "-w"
	arg7 := "2"  //wait time (in seconds)
	arg8 := "-n" //no dns resolution
	arg9 := "64" //packet size, bytes

	cmd := exec.Command(app, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, targetHost, arg9) //execute the commands above, with the host passed
	out, err := cmd.Output()                                                                         //output the results of the command

	if err != nil {
		fmt.Printf(err.Error())
		return
	}
	//fmt.Printf("%s\n", string(out))
	traceResult := findIPaddr(string(out))
	//fmt.Printf("%q\n", traceResult)
	var ipArray = make([]string, 0)
	dnsPtr := ""
	asnResult := ""
	for i := 2; i < len(traceResult); i++ {
		currIpAddr := traceResult[i][0]
		reverseDNSaddr, _ := net.LookupAddr(currIpAddr)
		if len(reverseDNSaddr) > 0 {
			//fmt.Printf("%s\n", reverseDNSaddr[0])
			dnsPtr = reverseDNSaddr[0] //if it has a PTR, put it in the PTR array section
		} else {
			dnsPtr = "noPTR" //everything that does not have a PTR listed
		}

		reverseIPaddrResult := reverseIPaddr(currIpAddr)                 //call the function to reverse the IP address
		dnsQueryAddress := reverseIPaddrResult + ".origin.asn.cymru.com" //query team cymru database for IP to ASN
		ipToAsnLookup, _ := net.LookupTXT(dnsQueryAddress)               //get TXT record result
		if len(ipToAsnLookup) > 0 {
			asnIndex := strings.Index(ipToAsnLookup[0], " ") //if so, parse out the ASN from the result
			queryString := ipToAsnLookup[0]
			asnResult = queryString[0:asnIndex]
		} else {
			asnResult = "noASN"
		}

		ipRowString := currIpAddr + "," + dnsPtr + "," + asnResult
		ipArray = append(ipArray, ipRowString)

	}
	//fmt.Printf("%d\n", len(traceIpArray))
	//fmt.Printf("%q\n", ipArray)
	ipChan <- ipArray
	waitChan <- 1
	return
}
Пример #5
0
func (d Domain) txt() string {
	addrs, err := net.LookupTXT(d.domain)
	if err != nil {
		return "\nTXT records\n" +
			"--\n" + err.Error()
	}
	records := "\nTXT records\n" +
		"--\n"
	for _, val := range addrs {
		records += val + "\n"
	}
	return records
}
func resourceDnsTxtRecordCreate(d *schema.ResourceData, meta interface{}) error {
	d.SetId(d.Get("name").(string))
	records, err := net.LookupTXT(d.Id())
	if err != nil {
		return err
	}

	if len(records) > 0 {
		d.Set("record", records[0])
	}
	d.Set("records", records)
	return nil
}
func dataSourceDnsTxtRecordRead(d *schema.ResourceData, meta interface{}) error {
	records, err := net.LookupTXT(d.Get("host").(string))
	if err != nil {
		return err
	}

	if len(records) > 0 {
		d.Set("record", records[0])
	} else {
		d.Set("record", "")
	}
	d.Set("records", records)
	return nil
}
Пример #8
0
// MustResolveOneIPByName takes in a string and returns the single
// string value for the IP which is being resolved.
// If it fails, or returns other values, panic
func MustResolveOneTXTByName(name string) string {
	// Do the resolve
	t, err := net.LookupTXT(name)
	// Check the initial error and panic if need be
	if err != nil {
		panic(err)
	}
	// Check for multiple return values
	if len(t) != 1 {
		panic(fmt.Errorf("Invalid response: %v", t))
	}
	// Return the single value
	return t[0]
}
Пример #9
0
func CountryForIPString(ipstr string) (country string, err error) {
	rev, err := reverseIP(ipstr)
	if err != nil {
		return "", err
	}
	query := fmt.Sprintf("%s.%s", rev, *flCountriesZone)
	txtList, err := net.LookupTXT(query)
	if err != nil {
		return "", err
	}
	if len(txtList) > 0 {
		return strings.ToUpper(txtList[0]), nil
	}
	return "", fmt.Errorf("No TXT records (and no error) for: %s", query)
}
func resourceDnsTxtRecordRead(d *schema.ResourceData, meta interface{}) error {
	// Read if forcing an update, or we haven't yet read any records
	if d.Get("update").(bool) {
		records, err := net.LookupTXT(d.Id())
		if err != nil {
			return err
		}

		if len(records) > 0 {
			d.Set("record", records[0])
		}
		d.Set("records", records)
	}
	return nil
}
Пример #11
0
// ResolveOneIPByName takes in a string and returns a string and error
// indicator. The error indicator is used if the resolve fails or returns
// multiple values.
func ResolveOneTXTByName(name string) (string, error) {
	// Do the resolve
	t, err := net.LookupTXT(name)
	// Check the initial error and return that if present
	if err != nil {
		return "", err
	}
	// Check for multiple IPs. If so, send back an error w/ "Multiple IPs returned"
	if len(t) != 1 {
		err = fmt.Errorf("Multiple TXT records returned")
		return "", err
	}
	// Return the single value
	return t[0], nil
}
Пример #12
0
func txt(host string) (data []byte, err error) {
	txts, err := net.LookupTXT(host)
	if err != nil {
		err = os.ErrNotExist
		return
	}

	buf := bytes.NewBuffer(make([]byte, 0, len(txts)*80))

	for _, txt := range txts {
		buf.WriteString(txt)
		buf.WriteByte('\n')
	}
	data = buf.Bytes()
	return
}
Пример #13
0
Файл: icsi.go Проект: ebfe/icsi
func Query(hash []byte) (*Response, error) {
	txts, err := net.LookupTXT(dnsname(hash))
	if err != nil {
		if isnxdomain(err) {
			return nil, nil
		}
		return nil, err
	}

	if len(txts) != 1 {
		return nil, errMultipleRecords
	}

	return parseResponse(txts[0])

}
Пример #14
0
func GetPksAuthTXTRecord(domain string) (pksAuth PksAuthTXT, err error) {
	txts, err1 := net.LookupTXT(domain)
	found := false
	if err1 != nil {
		log.Println(err1)
		err = err1
		return
	}
	net.LookupAddr(domain)

	for _, r := range txts {
		//log.Println("TXT of " + domain + " : " + r)
		rcds := strings.Split(r, "=")
		if len(rcds) != 2 {
			log.Println("Not Found = in TXT Record of " + domain)
		} else if rcds[0] != "pks" {
			log.Println("pks not found in TXT Record of " + domain)
		} else {
			rcds = strings.Split(rcds[1], " ")
			if len(rcds) != 3 {
				log.Println("Not Enough values in TXT Record of domain " + domain)
			} else {
				pksAuth.authAddr = rcds[0]
				//fmt.Println("pks_Addr=", rcds[0])
				//fmt.Println("key_FingerPrint=", rcds[1])
				pksAuth.keyFingerPrint = rcds[1]
				since, err2 := strconv.Atoi(rcds[2])
				if err2 != nil {
					log.Println(err2)
					err = err2
					return
				}
				pksAuth.since = int64(since)
				found = true
				break
				//fmt.Println("time=", time.Unix(int64(since), 0))
			}

		}
	}
	if found == false {
		err = errors.New("TXT Record of domain " + domain + "doesnt contain valid pksAuth Record")
		return

	}
	return
}
Пример #15
0
Файл: qdns.go Проект: 41px/qdns
func ltxt(domain string) {
	txts, err := net.LookupTXT(domain)

	if err != nil {
		//fmt.Printf("err:%s\n", err)
		return
	}

	fmt.Printf("-----------------\n")
	fmt.Printf(" Information TXT \n")
	fmt.Printf("-----------------\n")

	for _, txt := range txts {
		fmt.Printf("\t%s\n", txt)
	}

}
Пример #16
0
func (rc *DNSChecker) CheckDomain(sig string, domain string) ProofError {
	txt, err := net.LookupTXT(domain)
	if err != nil {
		return NewProofError(keybase1.ProofStatus_DNS_ERROR,
			"DNS failure for %s: %s", domain, err)
	}

	for _, record := range txt {
		G.Log.Debug("For %s, got TXT record: %s", domain, record)
		if record == sig {
			return nil
		}
	}
	return NewProofError(keybase1.ProofStatus_NOT_FOUND,
		"Checked %d TXT entries of %s, but didn't find signature %s",
		len(txt), domain, sig)
}
Пример #17
0
func handler(w http.ResponseWriter, r *http.Request) {
	parts := strings.Split(r.Host, ":")
	host := parts[0]

	hostname := fmt.Sprintf("_redirect.%s", host)
	txt, err := net.LookupTXT(hostname)
	if err != nil {
		fallback(w, r, fmt.Sprintf("Could not resolve hostname (%v)", err))
		return
	}

	redirect, err := getRedirect(txt, r.URL.String())
	if err != nil {
		fallback(w, r, err.Error())
	} else {
		http.Redirect(w, r, redirect.Location, redirect.Status)
	}
}
Пример #18
0
func (GoogleCatalogVerifier) Check(address string, fingerprint string) (fp string, err error) {
	fp = strings.ToLower(fingerprint)

	txts, err := net.LookupTXT(fp + "." + GOOGLE_CATALOG)
	if err != nil {
		return "", err
	}

	if len(txts) > 0 {
		return fingerprint, nil
	}

	//ok, google has seen this one. But how long ago?*/

	//t := time.Now().UTC().Unix()
	//currentDay := t / int64(60*60*24)

	return "", errors.New("google catalog didn't contain ")
}
Пример #19
0
func dns(w http.ResponseWriter, r *http.Request) {
	q := r.URL.Query().Get("q")
	// Note that the below is NOT safe from input attacks, but that's OK
	// because this is just for debugging.
	fmt.Fprintf(w, `<html><body>
<form action="/dns">
<input name="q" type="text" value="%v"></input>
<button type="submit">Lookup</button>
</form>
<br/><br/><pre>`, q)
	{
		res, err := net.LookupNS(q)
		spew.Fprintf(w, "LookupNS(%v):\nResult: %#v\nError: %v\n\n", q, res, err)
	}
	{
		res, err := net.LookupTXT(q)
		spew.Fprintf(w, "LookupTXT(%v):\nResult: %#v\nError: %v\n\n", q, res, err)
	}
	{
		cname, res, err := net.LookupSRV("", "", q)
		spew.Fprintf(w, `LookupSRV("", "", %v):
cname: %v
Result: %#v
Error: %v

`, q, cname, res, err)
	}
	{
		res, err := net.LookupHost(q)
		spew.Fprintf(w, "LookupHost(%v):\nResult: %#v\nError: %v\n\n", q, res, err)
	}
	{
		res, err := net.LookupIP(q)
		spew.Fprintf(w, "LookupIP(%v):\nResult: %#v\nError: %v\n\n", q, res, err)
	}
	{
		res, err := net.LookupMX(q)
		spew.Fprintf(w, "LookupMX(%v):\nResult: %#v\nError: %v\n\n", q, res, err)
	}
	fmt.Fprintf(w, `</pre>
</body>
</html>`)
}
Пример #20
0
// Given a SBL hit on a remote IP, try to give us what SBL records were hit.
func getSBLHits(t *smtpTransaction) []string {
	var sbls []string
	// since we know this hit, we can omit a lot of checks.
	s := strings.Split(t.rip, ".")
	ln := fmt.Sprintf("%s.%s.%s.%s.sbl.spamhaus.org.", s[3], s[2], s[1], s[0])
	txts, err := net.LookupTXT(ln)
	if err != nil {
		return sbls
	}
	for _, txt := range txts {
		idx := strings.LastIndex(txt, "/")
		if idx == -1 || idx == len(txt)-1 {
			continue
		}
		sbls = append(sbls, txt[idx+1:])
	}
	sort.Strings(sbls)
	return sbls
}
Пример #21
0
func main() {
	var err error
	cmdFlags()
	flag.Parse()
	if interfaces, err = net.Interfaces(); err != nil {
		panic(err)
	}
	if interfaceAddrs, err = net.InterfaceAddrs(); err != nil {
		panic(err)
	}
	if Options.listInterfaces {
		listInterfaces(interfaces)
	} else if Options.listInterfaceAddrs {
		listInterfaceAddrs(interfaceAddrs)
	} else if Options.rdns != "" {
		hostnames, _ := net.LookupAddr(Options.rdns)
		for _, hostname := range hostnames {
			fmt.Println(hostname)
		}
	} else if Options.ip != "" {
		ips, _ := net.LookupIP(Options.ip)
		for _, ip := range ips {
			fmt.Println(ip)
		}
	} else if Options.mx != "" {
		mxs, _ := net.LookupMX(Options.mx)
		for _, mx := range mxs {
			fmt.Println(mx.Pref, mx.Host)
		}
	} else if Options.ns != "" {
		nss, _ := net.LookupNS(Options.ns)
		for _, ns := range nss {
			fmt.Println(ns.Host)
		}
	} else if Options.txt != "" {
		txts, _ := net.LookupTXT(Options.txt)
		for _, txt := range txts {
			fmt.Println(txt)
		}
	}
}
Пример #22
0
// Resolve implements Resolver
// TXT records for a given domain name should contain a b58
// encoded multihash.
func (r *DNSResolver) Resolve(name string) (string, error) {
	log.Info("DNSResolver resolving %v", name)
	txt, err := net.LookupTXT(name)
	if err != nil {
		return "", err
	}

	for _, t := range txt {
		chk := b58.Decode(t)
		if len(chk) == 0 {
			continue
		}

		_, err := mh.Cast(chk)
		if err != nil {
			continue
		}
		return t, nil
	}

	return "", ErrResolveFailed
}
Пример #23
0
// Query will query a single dnsbl server about a host and return a struct
// containing information returned by the dnsbl server.
func Query(rbl, host string) (r Result, err error) {
	// Format the host address in the format of google.com.bad.example.com or
	// 99.2.0.192.bad.example.com
	name := fmt.Sprintf("%s.%s", host, rbl)

	addrs, err := net.LookupHost(name)
	if err != nil {
		return
	}

	// Check if the dnsbl server replied with an A record that points to
	// a local address such as 127.0.0.0/8 or [::1].
	if len(addrs) == 0 {
		return
	}

	// Check if the address returned by the dnsbl is an address that
	// has 127 as the first octet. If this is true then we can safely
	// assume that the host or IP is on the dnsrbl.
	if net.ParseIP(addrs[0]).IsLoopback() {
		r.Listed = true
	}

	// A dnsbl may return a txt record explaining why the host or IP
	// is on the list.
	txts, err := net.LookupTXT(name)
	if err != nil {
		return
	}

	// Usually only the first txt first is populated so we don't need to
	// loop through them.
	if len(txts) != 0 {
		r.Text = txts[0]
	}
	return
}
Пример #24
0
func serve(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, fmt.Sprintf("This resource does not accept %s requests.", r.Method), http.StatusMethodNotAllowed)
		return
	}

	domain := r.URL.Path[1:]

	h := w.Header()
	h.Set("Content-Type", "application/json; charset=utf-8")
	h.Set("Cache-Control", "public, max-age=900")
	h.Set("Access-Control-Allow-Origin", "*")

	srvFound := true
	_, srv, err := net.LookupSRV("xmpp-client", "tcp", domain)
	if err != nil {
		if !strings.HasSuffix(err.Error(), "DNS name does not exist.") {
			log.Printf("Error resolving SRV records for %q: %v", domain, err)
			httpError(w, internalServerError, http.StatusInternalServerError)
			return
		}

		srvFound = false
	}

	txtFound := true
	txt, err := net.LookupTXT("_xmppconnect." + domain)
	if err != nil {
		if !strings.HasSuffix(err.Error(), "DNS name does not exist.") {
			log.Printf("Error resolving TXT records for %q: %v", domain, err)
			httpError(w, internalServerError, http.StatusInternalServerError)
			return
		}

		txtFound = false
	}

	if !txtFound && !srvFound {
		httpError(w, notFoundError, http.StatusNotFound)
		return
	}

	res := &response{
		Version: "1.0",

		Data: &struct {
			Servers      serverList      `json:"servers"`
			Alternatives alternativeList `json:"alternatives"`
		}{
			Servers:      make([]*server, len(srv)),
			Alternatives: make([]*alternative, len(txt)),
		},
	}

	for i, service := range srv {
		res.Data.Servers[i] = &server{
			Target:   service.Target,
			Port:     service.Port,
			Priority: service.Priority,
			Weight:   service.Weight,
		}
	}

	for i, rec := range txt {
		split := strings.SplitN(rec, "=", 2)

		name := split[0]
		if !strings.HasPrefix(strings.ToLower(name), "_xmpp-client-") {
			continue
		}

		name = name[13:]

		res.Data.Alternatives[i] = &alternative{
			Name:  name,
			Value: split[1],
		}
	}

	if len(res.Data.Servers) == 0 && len(res.Data.Alternatives) == 0 {
		httpError(w, notFoundError, http.StatusNotFound)
		return
	}

	sort.Sort(res.Data.Servers)
	sort.Sort(res.Data.Alternatives)

	encoded, err := json.Marshal(res)
	if err != nil {
		log.Fatalf("Error marshalling JSON for %q: %v", domain, err)
	}

	hash := crc64.Checksum(encoded, crcTable)

	h.Set("ETag", "\""+strconv.FormatUint(hash, 16)+"\"")

	content := bytes.NewReader(encoded)
	http.ServeContent(w, r, domain, time.Time{}, content)
}
Пример #25
0
func resolvTXT(addr string) string {
	txts, _ := net.LookupTXT(addr)
	return strings.Join(txts, ", ")
}
Пример #26
0
// Process request
func Process(sEmail string, sHeader string) (Reply, error) {
	var r Reply
	var sIP string
	var sDomain string
	var sReceived = sHeader
	var bSPFPass bool = false
	var ApprovedIPs []string

	// Init
	_, sDomain = SplitAddress(sEmail)
	r.Email = sEmail
	r.Header = sHeader
	r.Domain = sDomain
	r.IP = sIP

	// Get records of sender domain
	records, _ := net.LookupTXT(sDomain)
	sSPF := TraverseSPF(records)
	//fmt.Printf("\n\n\nFinal: %s", sSPF)
	SPF := strings.Split(sSPF, " ")

	// Now let's only look at IPs
	for _, el := range SPF {
		if strings.Contains(el, "ip4:") {
			ApprovedIPs = append(ApprovedIPs, el)
		}
		//TODO: ipv6
	}

	// See if received from is valid sender
	ips, _ := net.LookupIP(sReceived)
	for _, ip := range ips {
		//fmt.Printf("\nFound %v", ip)
		r.IP = ip.String()
		for _, el := range ApprovedIPs {
			// See if IP in spf
			if strings.Contains(el, ip.String()) {
				bSPFPass = true
				break
				// If this is a network block, do lookup
			} else if strings.Contains(el, "/") {
				//fmt.Printf("\n	Resolving cidr of %v", el)
				_, cidrNet, _ := net.ParseCIDR(strings.Replace(strings.Replace(el, "ip4:", "", -1), "ip6:", "", -1))
				if cidrNet.Contains(ip) {
					bSPFPass = true
					break
				}
			}
		}

		// See if IP in any networks of spf
	}

	//fmt.Printf("\n\n")
	//for _, ip := range ips {
	//	fmt.Printf("\nSent by %s", ip.String())
	//}

	// Build success reply
	r.Result = "Fail"
	if bSPFPass {
		r.Result = "Pass"
	}

	return r, nil
}
Пример #27
0
func newPubKeyFromDnsTxt(selector, domain string) (*pubKeyRep, verifyOutput, error) {
	txt, err := net.LookupTXT(selector + "._domainkey." + domain)
	if err != nil {
		if strings.HasSuffix(err.Error(), "no such host") {
			return nil, PERMFAIL, ErrVerifyNoKeyForSignature
		} else {
			return nil, TEMPFAIL, ErrVerifyKeyUnavailable
		}
	}

	// empty record
	if len(txt) == 0 {
		return nil, PERMFAIL, ErrVerifyNoKeyForSignature
	}

	pkr := new(pubKeyRep)
	pkr.Version = "DKIM1"
	pkr.HashAlgo = []string{"sha1", "sha256"}
	pkr.KeyType = "rsa"
	pkr.ServiceType = []string{"all"}
	pkr.FlagTesting = false
	pkr.FlagIMustBeD = false

	// parsing, we keep the first record
	// TODO: if there is multiple record

	p := strings.Split(txt[0], ";")
	for i, data := range p {
		keyVal := strings.SplitN(data, "=", 2)
		val := ""
		if len(keyVal) > 1 {
			val = strings.TrimSpace(keyVal[1])
		}
		switch strings.ToLower(strings.TrimSpace(keyVal[0])) {
		case "v":
			// RFC: is this tag is specified it MUST be the first in the record
			if i != 0 {
				return nil, PERMFAIL, ErrVerifyTagVMustBeTheFirst
			}
			pkr.Version = val
			if pkr.Version != "DKIM1" {
				return nil, PERMFAIL, ErrVerifyVersionMusBeDkim1
			}
		case "h":
			p := strings.Split(strings.ToLower(val), ":")
			pkr.HashAlgo = []string{}
			for _, h := range p {
				h = strings.TrimSpace(h)
				if h == "sha1" || h == "sha256" {
					pkr.HashAlgo = append(pkr.HashAlgo, h)
				}
			}
			// if empty switch back to default
			if len(pkr.HashAlgo) == 0 {
				pkr.HashAlgo = []string{"sha1", "sha256"}
			}
		case "k":
			if strings.ToLower(val) != "rsa" {
				return nil, PERMFAIL, ErrVerifyBadKeyType
			}
		case "n":
			pkr.Note = val
		case "p":
			rawkey := val
			if rawkey == "" {
				return nil, PERMFAIL, ErrVerifyRevokedKey
			}
			un64, err := base64.StdEncoding.DecodeString(rawkey)
			if err != nil {
				return nil, PERMFAIL, ErrVerifyBadKey
			}
			pk, err := x509.ParsePKIXPublicKey(un64)
			pkr.PubKey = *pk.(*rsa.PublicKey)
		case "s":
			t := strings.Split(strings.ToLower(val), ":")
			for _, tt := range t {
				if tt == "*" {
					pkr.ServiceType = []string{"all"}
					break
				}
				if tt == "email" {
					pkr.ServiceType = []string{"email"}
				}
			}
		case "t":
			flags := strings.Split(strings.ToLower(val), ":")
			for _, flag := range flags {
				if flag == "y" {
					pkr.FlagTesting = true
					continue
				}
				if flag == "s" {
					pkr.FlagIMustBeD = true
				}
			}
		}
	}

	// if no pubkey
	if pkr.PubKey == (rsa.PublicKey{}) {
		return nil, PERMFAIL, ErrVerifyNoKey
	}

	return pkr, SUCCESS, nil
}
Пример #28
0
func resolveSRV(uri *URI, proto string) (*e3x.Identity, error) {
	// ignore port
	host, _, _ := net.SplitHostPort(uri.Canonical)
	if host == "" {
		host = uri.Canonical
	}

	// normalize
	if !strings.HasSuffix(host, ".") {
		host += "."
	}

	// ignore .public
	if strings.HasSuffix(host, ".public.") {
		return nil, &net.DNSError{Name: host, Err: "cannot resolve .public hostnames using DNS"}
	}

	// lookup SRV records
	_, srvs, err := net.LookupSRV("mesh", proto, host)
	if err != nil {
		return nil, err
	}
	if len(srvs) > 1 {
		return nil, &net.DNSError{Name: host, Err: "too many SRV records"}
	}
	if len(srvs) == 0 {
		return nil, &net.DNSError{Name: host, Err: "no SRV records"}
	}

	var (
		srv     = srvs[0]
		port    = srv.Port
		portStr = strconv.Itoa(int(port))
		hn      hashname.H
		keys    cipherset.Keys
	)

	{ // detect valid target
		parts := strings.SplitN(srv.Target, ".", 2)
		if len(parts) != 2 || len(parts[0]) != 52 || len(parts[1]) == 0 {
			return nil, &net.DNSError{Name: host, Err: "SRV must target a <hashname>.<domain> domain"}
		}

		hn = hashname.H(parts[0])
		if !hn.Valid() {
			return nil, &net.DNSError{Name: host, Err: "SRV must target a <hashname>.<domain> domain"}
		}
	}

	// detect CNAMEs (they are not allowed)
	cname, err := net.LookupCNAME(srv.Target)
	if err != nil {
		return nil, err
	}
	if cname != "" && cname != srv.Target {
		return nil, &net.DNSError{Name: host, Err: "CNAME record are not allowed"}
	}

	// lookup A AAAA records
	ips, err := net.LookupIP(srv.Target)
	if err != nil {
		return nil, err
	}
	if len(ips) == 0 {
		return nil, &net.DNSError{Name: host, Err: "no A or AAAA records"}
	}

	// lookup TXT
	txts, err := net.LookupTXT(srv.Target)
	if err != nil {
		return nil, err
	}
	if len(txts) == 0 {
		return nil, &net.DNSError{Name: host, Err: "no TXT records"}
	}

	// make addrs
	addrs := make([]net.Addr, 0, len(ips))
	for _, ip := range ips {
		var (
			addr net.Addr
		)

		switch proto {
		case "udp":
			addr, _ = transports.ResolveAddr("udp4", net.JoinHostPort(ip.String(), portStr))
			if addr == nil {
				addr, _ = transports.ResolveAddr("udp6", net.JoinHostPort(ip.String(), portStr))
			}
		case "tcp":
			addr, _ = transports.ResolveAddr("tcp4", net.JoinHostPort(ip.String(), portStr))
			if addr == nil {
				addr, _ = transports.ResolveAddr("tcp6", net.JoinHostPort(ip.String(), portStr))
			}
			// case "http":
			// 	addr, _ = http.NewAddr(ip, port)
		}

		if addr != nil {
			addrs = append(addrs, addr)
		}
	}

	{ // parse keys

		// Sort txts so they form ascending sequences of key parts
		sort.Strings(txts)

		keyData := make(map[uint8]string, 10)
		for len(txts) > 0 {
			var (
				txt   = txts[0]
				parts = strings.Split(txt, "=")
			)

			if len(parts) != 2 {
				txts = txts[1:]
				continue
			}

			var (
				label = parts[0]
				value = parts[1]
				csid  uint8
			)

			if len(label) < 2 {
				txts = txts[1:]
				continue
			}

			// parse the CSID portion of the label
			i, err := strconv.ParseUint(label[:2], 16, 8)
			if err != nil {
				txts = txts[1:]
				continue
			}
			csid = uint8(i)

			// verify the key-part portion of the label
			if len(label) > 2 {
				_, err = strconv.ParseUint(label[2:], 10, 8)
				if err != nil {
					txts = txts[1:]
					continue
				}
			}

			keyData[csid] += value
			txts = txts[1:]
		}

		keys = make(cipherset.Keys, len(keyData))
		for csid, str := range keyData {
			key, err := cipherset.DecodeKey(csid, str, "")
			if err != nil {
				continue
			}

			keys[csid] = key
		}
	}

	ident, err := e3x.NewIdentity(keys, nil, addrs)
	if err != nil {
		return nil, err
	}

	if hn != ident.Hashname() {
		return nil, &net.DNSError{Name: host, Err: "invalid keys"}
	}

	return ident, nil
}
Пример #29
0
func configure(hub *StatusHub) {

	cfg, err := configRead(*configFile)
	if err != nil {
		log.Printf("Could not read config file: %s\n", err)
		os.Exit(2)
	}

	hub.MarkConfigurationStart()
	wg := &sync.WaitGroup{}
	errch := make(chan error, 20)

	for _, server := range cfg.Servers.A {
		log.Println("Adding", server)
		wg.Add(1)
		hub.AddNameBackground(server, errch)
	}

	for _, domain := range cfg.Servers.Domain {
		log.Println("Adding NSes for", domain)

		nses, err := net.LookupNS(domain)

		log.Printf("NSes: %#v: %s\n", nses, err)
		for _, ns := range nses {
			log.Printf("Adding '%s'\n", ns.Host)
			wg.Add(1)
			hub.AddNameBackground(ns.Host, errch)
		}
	}

	for _, txtconfig := range cfg.Servers.Txt {

		x := strings.SplitN(txtconfig, ",", 2)
		txtname := strings.TrimSpace(x[0])
		txtbase := strings.TrimSpace(x[1])

		log.Println("Adding TXT for", txtname, txtbase)

		txts, err := net.LookupTXT(txtname)
		log.Printf("TXTs: %#v: %s\n", txts, err)

		names := []string{}

		for _, txt := range txts {
			for _, name := range strings.Split(txt, " ") {
				names = append(names, name)
			}
		}

		nameSlice := []string{"", txtbase}
		for _, name := range names {
			nameSlice[0] = name
			hub.AddNameBackground(strings.Join(nameSlice, "."), errch)
		}
	}

	go func() {
		for err := range errch {
			if err != nil {
				log.Println(err)
			}
			wg.Done()
		}
	}()

	wg.Wait()
	close(errch)
	hub.MarkConfigurationEnd()

}