]> Sergey Matveev's repositories - tofuproxy.git/blob - dane.go
Initial commit
[tofuproxy.git] / dane.go
1 /*
2 Copyright (C) 2021 Sergey Matveev <stargrave@stargrave.org>
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, version 3 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 package main
18
19 import (
20         "crypto/sha256"
21         "crypto/sha512"
22         "crypto/x509"
23         "encoding/hex"
24         "fmt"
25         "log"
26         "strings"
27
28         "github.com/miekg/dns"
29 )
30
31 func dane(addr string, cert *x509.Certificate) (bool, bool) {
32         if *dnsSrv == "" {
33                 return false, false
34         }
35         host := addr
36         port := "443"
37         cols := strings.Split(addr, ":")
38         if len(cols) > 1 {
39                 host = cols[0]
40                 port = cols[1]
41         }
42         m := new(dns.Msg)
43         m.SetQuestion(dns.Fqdn(fmt.Sprintf("_%s._tcp.%s", port, host)), dns.TypeTLSA)
44         msg, err := dns.Exchange(m, *dnsSrv)
45         if err != nil {
46                 log.Printf("DNS: %+v\n", err)
47                 return false, false
48         }
49         if msg.MsgHdr.Rcode != dns.RcodeSuccess {
50                 return false, false
51         }
52         exists := false
53         for _, answer := range msg.Answer {
54                 tlsa, ok := answer.(*dns.TLSA)
55                 if !ok {
56                         continue
57                 }
58                 if tlsa.Usage != 3 {
59                         // Non EE
60                         continue
61                 }
62                 exists = true
63                 var toMatch []byte
64                 switch tlsa.Selector {
65                 case 0:
66                         toMatch = cert.Raw
67                 case 1:
68                         toMatch = cert.RawSubjectPublicKeyInfo
69                 }
70                 var hsh []byte
71                 switch tlsa.MatchingType {
72                 case 1:
73                         our := sha256.Sum256(toMatch)
74                         hsh = our[:]
75                 case 2:
76                         our := sha512.Sum512(toMatch)
77                         hsh = our[:]
78                 }
79                 if tlsa.Certificate == hex.EncodeToString(hsh) {
80                         return true, true
81                 }
82         }
83         return exists, false
84 }