| 
									
										
										
										
											2016-04-26 17:57:11 +01:00
										 |  |  | package dnssec | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"crypto" | 
					
						
							|  |  |  | 	"crypto/ecdsa" | 
					
						
							|  |  |  | 	"crypto/rsa" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-21 22:51:47 -08:00
										 |  |  | 	"github.com/coredns/coredns/request" | 
					
						
							| 
									
										
										
										
											2016-04-26 17:57:11 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/miekg/dns" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-23 09:14:12 +01:00
										 |  |  | // DNSKEY holds a DNSSEC public and private key used for on-the-fly signing. | 
					
						
							| 
									
										
										
										
											2016-04-26 17:57:11 +01:00
										 |  |  | type DNSKEY struct { | 
					
						
							| 
									
										
										
										
											2017-10-20 09:22:02 +01:00
										 |  |  | 	K   *dns.DNSKEY | 
					
						
							|  |  |  | 	D   *dns.DS | 
					
						
							|  |  |  | 	s   crypto.Signer | 
					
						
							|  |  |  | 	tag uint16 | 
					
						
							| 
									
										
										
										
											2016-04-26 17:57:11 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ParseKeyFile read a DNSSEC keyfile as generated by dnssec-keygen or other | 
					
						
							|  |  |  | // utilities. It adds ".key" for the public key and ".private" for the private key. | 
					
						
							|  |  |  | func ParseKeyFile(pubFile, privFile string) (*DNSKEY, error) { | 
					
						
							|  |  |  | 	f, e := os.Open(pubFile) | 
					
						
							|  |  |  | 	if e != nil { | 
					
						
							|  |  |  | 		return nil, e | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-20 17:35:59 +02:00
										 |  |  | 	defer f.Close() | 
					
						
							| 
									
										
										
										
											2016-04-26 17:57:11 +01:00
										 |  |  | 	k, e := dns.ReadRR(f, pubFile) | 
					
						
							|  |  |  | 	if e != nil { | 
					
						
							|  |  |  | 		return nil, e | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f, e = os.Open(privFile) | 
					
						
							|  |  |  | 	if e != nil { | 
					
						
							|  |  |  | 		return nil, e | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-20 17:35:59 +02:00
										 |  |  | 	defer f.Close() | 
					
						
							| 
									
										
										
										
											2017-10-20 09:22:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-31 07:14:49 +00:00
										 |  |  | 	dk, ok := k.(*dns.DNSKEY) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return nil, errors.New("no public key found") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-20 09:22:02 +01:00
										 |  |  | 	p, e := dk.ReadPrivateKey(f, privFile) | 
					
						
							| 
									
										
										
										
											2016-04-26 17:57:11 +01:00
										 |  |  | 	if e != nil { | 
					
						
							|  |  |  | 		return nil, e | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-20 09:22:02 +01:00
										 |  |  | 	if s, ok := p.(*rsa.PrivateKey); ok { | 
					
						
							|  |  |  | 		return &DNSKEY{K: dk, D: dk.ToDS(dns.SHA256), s: s, tag: dk.KeyTag()}, nil | 
					
						
							| 
									
										
										
										
											2016-04-26 17:57:11 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-20 09:22:02 +01:00
										 |  |  | 	if s, ok := p.(*ecdsa.PrivateKey); ok { | 
					
						
							|  |  |  | 		return &DNSKEY{K: dk, D: dk.ToDS(dns.SHA256), s: s, tag: dk.KeyTag()}, nil | 
					
						
							| 
									
										
										
										
											2016-04-26 17:57:11 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-31 07:14:49 +00:00
										 |  |  | 	return &DNSKEY{K: dk, D: dk.ToDS(dns.SHA256), s: nil, tag: 0}, errors.New("no private key found") | 
					
						
							| 
									
										
										
										
											2016-04-26 17:57:11 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // getDNSKEY returns the correct DNSKEY to the client. Signatures are added when do is true. | 
					
						
							| 
									
										
										
										
											2018-04-27 19:37:31 +01:00
										 |  |  | func (d Dnssec) getDNSKEY(state request.Request, zone string, do bool, server string) *dns.Msg { | 
					
						
							| 
									
										
										
										
											2016-04-26 17:57:11 +01:00
										 |  |  | 	keys := make([]dns.RR, len(d.keys)) | 
					
						
							|  |  |  | 	for i, k := range d.keys { | 
					
						
							|  |  |  | 		keys[i] = dns.Copy(k.K) | 
					
						
							|  |  |  | 		keys[i].Header().Name = zone | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	m := new(dns.Msg) | 
					
						
							|  |  |  | 	m.SetReply(state.Req) | 
					
						
							|  |  |  | 	m.Answer = keys | 
					
						
							|  |  |  | 	if !do { | 
					
						
							|  |  |  | 		return m | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	incep, expir := incepExpir(time.Now().UTC()) | 
					
						
							| 
									
										
										
										
											2018-04-27 19:37:31 +01:00
										 |  |  | 	if sigs, err := d.sign(keys, zone, 3600, incep, expir, server); err == nil { | 
					
						
							| 
									
										
										
										
											2016-04-26 17:57:11 +01:00
										 |  |  | 		m.Answer = append(m.Answer, sigs...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return m | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-10-20 17:35:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Return true iff this is a zone key with the SEP bit unset. This implies a ZSK (rfc4034 2.1.1). | 
					
						
							|  |  |  | func (k DNSKEY) isZSK() bool { | 
					
						
							| 
									
										
										
										
											2018-11-13 16:46:48 -05:00
										 |  |  | 	return k.K.Flags&(1<<8) == (1<<8) && k.K.Flags&1 == 0 | 
					
						
							| 
									
										
										
										
											2018-10-20 17:35:59 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Return true iff this is a zone key with the SEP bit set. This implies a KSK (rfc4034 2.1.1). | 
					
						
							|  |  |  | func (k DNSKEY) isKSK() bool { | 
					
						
							| 
									
										
										
										
											2018-11-13 16:46:48 -05:00
										 |  |  | 	return k.K.Flags&(1<<8) == (1<<8) && k.K.Flags&1 == 1 | 
					
						
							| 
									
										
										
										
											2018-10-20 17:35:59 +02:00
										 |  |  | } |