Merge #46: Apply "gofmt -s"

cf7518d Travis: Make gotype critical for gometalinter. (JeremyRand)
d058005 Travis: Make gofmt critical for gometalinter. (JeremyRand)
b6cf88d gofmt -s util/util_test.go (JeremyRand)
0da5cd2 gofmt -s util/util.go (JeremyRand)
6e3101e gofmt -s tlsrestrictchromium/tlsrestrict_chromium_tool/main.go (JeremyRand)
e3cd522 gofmt -s tlsrestrictchromium/chromium_test.go (JeremyRand)
2f0e866 gofmt -s tlsrestrictchromium/chromium.go (JeremyRand)
5152222 gofmt -s tlshook/tlshook.go (JeremyRand)
26b4c4c gofmt -s ncdomain/convert.go (JeremyRand)
1fb4007 gofmt -s generate_nmc_cert/main.go (JeremyRand)
53adb64 gofmt -s certinject/file.go (JeremyRand)
f70f23a gofmt -s certinject/cryptoapi_windows.go (JeremyRand)
6557714 gofmt -s certinject/certinject_windows.go (JeremyRand)
b1ab832 gofmt -s certinject_misc.go (JeremyRand)
8ec3281 gofmt -s certdehydrate/certdehydrate_test.go (JeremyRand)
62f0e6a gofmt -s certdehydrate/certdehydrate.go (JeremyRand)
e8feeb3 gofmt -s backend/backend.go (JeremyRand)

Pull request description:

  Based on recommendations from static analysis.

Tree-SHA512: 432d23656e552e93298eab2b3c32cf505aa503639a6cfc9498363b8208b697169392e36247ed029b8d54ddbe4fdfcc2cd36f2497ea22245de3703c95d4edf3b4
pull/51/head
JeremyRand 7 years ago
commit 236a432808
No known key found for this signature in database
GPG Key ID: B3F2D165786D6570

@ -25,11 +25,9 @@ gometalinter.v1 --enable-all \
--disable=errcheck \ --disable=errcheck \
--disable=gas \ --disable=gas \
--disable=gocyclo \ --disable=gocyclo \
--disable=gofmt \
--disable=goimports \ --disable=goimports \
--disable=golint \ --disable=golint \
--disable=gosimple \ --disable=gosimple \
--disable=gotype \
--disable=ineffassign \ --disable=ineffassign \
--disable=lll \ --disable=lll \
--disable=misspell \ --disable=misspell \

@ -422,12 +422,12 @@ func (tx *btx) _findNCValue(ncv *ncdomain.Value, isubname, subname string, depth
func (tx *btx) addAnswersUnderNCValueActual(ncv *ncdomain.Value, sn string) (rrs []dns.RR, err error) { func (tx *btx) addAnswersUnderNCValueActual(ncv *ncdomain.Value, sn string) (rrs []dns.RR, err error) {
rrs, err = ncv.RRs(nil, dns.Fqdn(tx.qname), dns.Fqdn(tx.basename+"."+tx.rootname)) rrs, err = ncv.RRs(nil, dns.Fqdn(tx.qname), dns.Fqdn(tx.basename+"."+tx.rootname))
// TODO: add callback variable "OnValueReferencedFunc" to backend options so that we don't pollute this function with every hook that we want // TODO: add callback variable "OnValueReferencedFunc" to backend options so that we don't pollute this function with every hook that we want
// might need to add the other attributes of tx, and sn, to the callback variable for flexibility's sake // might need to add the other attributes of tx, and sn, to the callback variable for flexibility's sake
// This doesn't normally return errors, but any errors during execution will be logged. // This doesn't normally return errors, but any errors during execution will be logged.
tlshook.DomainValueHookTLS(tx.qname, ncv) tlshook.DomainValueHookTLS(tx.qname, ncv)
return return
} }

@ -20,16 +20,16 @@ import "github.com/namecoin/ncdns/x509"
// https://github.com/namecoin/proposals/blob/master/ifa-0003.md // https://github.com/namecoin/proposals/blob/master/ifa-0003.md
// TODO: add a version field // TODO: add a version field
type DehydratedCertificate struct { type DehydratedCertificate struct {
PubkeyB64 string PubkeyB64 string
NotBeforeScaled int64 NotBeforeScaled int64
NotAfterScaled int64 NotAfterScaled int64
SignatureAlgorithm int64 SignatureAlgorithm int64
SignatureB64 string SignatureB64 string
} }
// SerialNumber calculates the certificate serial number according to the // SerialNumber calculates the certificate serial number according to the
// Dehydrated TLS Certificates specification. // Dehydrated TLS Certificates specification.
func (dehydrated DehydratedCertificate) SerialNumber(name string) ([]byte, error){ func (dehydrated DehydratedCertificate) SerialNumber(name string) ([]byte, error) {
nameHash := sha256.Sum256([]byte(name)) nameHash := sha256.Sum256([]byte(name))
@ -119,12 +119,12 @@ func ParseDehydratedCert(data interface{}) (*DehydratedCertificate, error) {
return nil, fmt.Errorf("Dehydrated cert signature must be a string") return nil, fmt.Errorf("Dehydrated cert signature must be a string")
} }
result := DehydratedCertificate { result := DehydratedCertificate{
PubkeyB64: pubkeyB64, PubkeyB64: pubkeyB64,
NotBeforeScaled: int64(notBeforeScaled), NotBeforeScaled: int64(notBeforeScaled),
NotAfterScaled: int64(notAfterScaled), NotAfterScaled: int64(notAfterScaled),
SignatureAlgorithm: int64(signatureAlgorithm), SignatureAlgorithm: int64(signatureAlgorithm),
SignatureB64: signatureB64, SignatureB64: signatureB64,
} }
return &result, nil return &result, nil
@ -155,11 +155,11 @@ func DehydrateCert(cert *x509.Certificate) (*DehydratedCertificate, error) {
signatureB64 := base64.StdEncoding.EncodeToString(signatureBytes) signatureB64 := base64.StdEncoding.EncodeToString(signatureBytes)
result := DehydratedCertificate{ result := DehydratedCertificate{
PubkeyB64: pubkeyB64, PubkeyB64: pubkeyB64,
NotBeforeScaled: notBeforeScaled, NotBeforeScaled: notBeforeScaled,
NotAfterScaled: notAfterScaled, NotAfterScaled: notAfterScaled,
SignatureAlgorithm: signatureAlgorithm, SignatureAlgorithm: signatureAlgorithm,
SignatureB64: signatureB64, SignatureB64: signatureB64,
} }
return &result, nil return &result, nil
@ -168,7 +168,7 @@ func DehydrateCert(cert *x509.Certificate) (*DehydratedCertificate, error) {
// RehydrateCert converts a dehydrated certificate into a standard x509 // RehydrateCert converts a dehydrated certificate into a standard x509
// certificate, but does not fill in the domain name or any fields that depend // certificate, but does not fill in the domain name or any fields that depend
// on it. The resulting certificate is intended to be used as input to // on it. The resulting certificate is intended to be used as input to
// FillRehydratedCertTemplate. // FillRehydratedCertTemplate.
func RehydrateCert(dehydrated *DehydratedCertificate) (*x509.Certificate, error) { func RehydrateCert(dehydrated *DehydratedCertificate) (*x509.Certificate, error) {
pubkeyBin, err := base64.StdEncoding.DecodeString(dehydrated.PubkeyB64) pubkeyBin, err := base64.StdEncoding.DecodeString(dehydrated.PubkeyB64)
@ -198,19 +198,19 @@ func RehydrateCert(dehydrated *DehydratedCertificate) (*x509.Certificate, error)
template := x509.Certificate{ template := x509.Certificate{
SerialNumber: big.NewInt(1), SerialNumber: big.NewInt(1),
NotBefore: notBefore, NotBefore: notBefore,
NotAfter: notAfter, NotAfter: notAfter,
// x509.KeyUsageKeyEncipherment is used for RSA key exchange, but not DHE/ECDHE key exchange. Since everyone should be using ECDHE (due to forward secrecy), we disallow x509.KeyUsageKeyEncipherment in our template. // x509.KeyUsageKeyEncipherment is used for RSA key exchange, but not DHE/ECDHE key exchange. Since everyone should be using ECDHE (due to forward secrecy), we disallow x509.KeyUsageKeyEncipherment in our template.
//KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, //KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
KeyUsage: x509.KeyUsageDigitalSignature, KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true, BasicConstraintsValid: true,
SignatureAlgorithm: signatureAlgorithm, SignatureAlgorithm: signatureAlgorithm,
PublicKey: pubkey, PublicKey: pubkey,
Signature: signature, Signature: signature,
} }
return &template, nil return &template, nil
@ -222,7 +222,7 @@ func RehydrateCert(dehydrated *DehydratedCertificate) (*x509.Certificate, error)
func FillRehydratedCertTemplate(template x509.Certificate, name string) ([]byte, error) { func FillRehydratedCertTemplate(template x509.Certificate, name string) ([]byte, error) {
template.Subject = pkix.Name{ template.Subject = pkix.Name{
CommonName: name, CommonName: name,
SerialNumber: "Namecoin TLS Certificate", SerialNumber: "Namecoin TLS Certificate",
} }

@ -1,39 +1,38 @@
package certdehydrate_test package certdehydrate_test
import ( import (
"testing"
"encoding/json" "encoding/json"
"reflect"
"github.com/namecoin/ncdns/certdehydrate" "github.com/namecoin/ncdns/certdehydrate"
"reflect"
"testing"
) )
func TestDehydratedCertIdentityOperation(t *testing.T) { func TestDehydratedCertIdentityOperation(t *testing.T) {
bytesJson := []byte(`[1, "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/hy1t4jB14ronx6n1m8VQh02jblRfu2cV3/LcyomfVljypUQMGjmuxWNbPI0a3cF6miNOijSCutqTZdb7TLvig==",4944096,5049216,10,"MEQCIGXXk6gYx95vQoknRwiQ4e27I+DXUWkE8L6dmLwAiGncAiBbtEX1nnZINx1YGzT5Fx8SxpjLwNDTUBkq22NpazHLIA=="]`) bytesJson := []byte(`[1, "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE/hy1t4jB14ronx6n1m8VQh02jblRfu2cV3/LcyomfVljypUQMGjmuxWNbPI0a3cF6miNOijSCutqTZdb7TLvig==",4944096,5049216,10,"MEQCIGXXk6gYx95vQoknRwiQ4e27I+DXUWkE8L6dmLwAiGncAiBbtEX1nnZINx1YGzT5Fx8SxpjLwNDTUBkq22NpazHLIA=="]`)
var parsedJson []interface{} var parsedJson []interface{}
if err := json.Unmarshal(bytesJson, &parsedJson); err != nil { if err := json.Unmarshal(bytesJson, &parsedJson); err != nil {
t.Error("Error parsing JSON:", err) t.Error("Error parsing JSON:", err)
} }
dehydrated, err := certdehydrate.ParseDehydratedCert(parsedJson) dehydrated, err := certdehydrate.ParseDehydratedCert(parsedJson)
if err != nil { if err != nil {
t.Error("Error parsing dehydrated certificate:", err) t.Error("Error parsing dehydrated certificate:", err)
} }
template, err := certdehydrate.RehydrateCert(dehydrated) template, err := certdehydrate.RehydrateCert(dehydrated)
if err != nil { if err != nil {
t.Error("Error rehydrating certificate:", err) t.Error("Error rehydrating certificate:", err)
} }
dehydrated2, err := certdehydrate.DehydrateCert(template) dehydrated2, err := certdehydrate.DehydrateCert(template)
if err != nil { if err != nil {
t.Error("Error dehydrating certificate:", err) t.Error("Error dehydrating certificate:", err)
} }
// Test to make sure that rehydrating and then dehydrating a cert doesn't change it. // Test to make sure that rehydrating and then dehydrating a cert doesn't change it.
if !reflect.DeepEqual(dehydrated, dehydrated2) { if !reflect.DeepEqual(dehydrated, dehydrated2) {
t.Error(dehydrated, "!=", dehydrated2) t.Error(dehydrated, "!=", dehydrated2)
} }
} }

@ -7,9 +7,9 @@ import "github.com/hlandau/xlog"
var log, Log = xlog.New("ncdns.certinject") var log, Log = xlog.New("ncdns.certinject")
func InjectCert(derBytes []byte) { func InjectCert(derBytes []byte) {
} }
func CleanCerts() { func CleanCerts() {
} }

@ -1,21 +1,20 @@
package certinject package certinject
import ( import (
"gopkg.in/hlandau/easyconfig.v1/cflag"
"github.com/hlandau/xlog" "github.com/hlandau/xlog"
"gopkg.in/hlandau/easyconfig.v1/cflag"
) )
// This package is used to add and remove certificates to the system trust
// This package is used to add and remove certificates to the system trust
// store. // store.
// Currently only supports Windows CryptoAPI. // Currently only supports Windows CryptoAPI.
var log, Log = xlog.New("ncdns.certinject") var log, Log = xlog.New("ncdns.certinject")
var ( var (
flagGroup = cflag.NewGroup(nil, "certstore") flagGroup = cflag.NewGroup(nil, "certstore")
cryptoApiFlag = cflag.Bool(flagGroup, "cryptoapi", false, "Synchronize TLS certs to the CryptoAPI trust store? This enables HTTPS to work with Chromium/Chrome. Only use if you've set up null HPKP in Chromium/Chrome as per documentation. If you haven't set up null HPKP, or if you access ncdns from browsers not based on Chromium or Firefox, this is unsafe and should not be used.") cryptoApiFlag = cflag.Bool(flagGroup, "cryptoapi", false, "Synchronize TLS certs to the CryptoAPI trust store? This enables HTTPS to work with Chromium/Chrome. Only use if you've set up null HPKP in Chromium/Chrome as per documentation. If you haven't set up null HPKP, or if you access ncdns from browsers not based on Chromium or Firefox, this is unsafe and should not be used.")
certExpirePeriod = cflag.Int(flagGroup, "expire", 60 * 30, "Duration (in seconds) after which TLS certs will be removed from the trust store. Making this smaller than the DNS TTL (default 600) may cause TLS errors.") certExpirePeriod = cflag.Int(flagGroup, "expire", 60*30, "Duration (in seconds) after which TLS certs will be removed from the trust store. Making this smaller than the DNS TTL (default 600) may cause TLS errors.")
) )
// Injects the given cert into all configured trust stores. // Injects the given cert into all configured trust stores.

@ -1,12 +1,12 @@
package certinject package certinject
import ( import (
"golang.org/x/sys/windows/registry"
"crypto/sha1" "crypto/sha1"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"strings" "golang.org/x/sys/windows/registry"
"math" "math"
"strings"
"time" "time"
) )
@ -64,7 +64,7 @@ func injectCertCryptoApi(derBytes []byte) {
certLength := len(derBytes) certLength := len(derBytes)
// Header for a stripped Windows Certificate Registry Blob // Header for a stripped Windows Certificate Registry Blob
certBlobHeader := []byte{0x20, 0, 0, 0, 0x01, 0, 0, 0, byte( (certLength >> 0) & 0xFF), byte( (certLength >> 8) & 0xFF), byte( (certLength >> 16) & 0xFF), byte( (certLength >> 24) & 0xFF) } certBlobHeader := []byte{0x20, 0, 0, 0, 0x01, 0, 0, 0, byte((certLength >> 0) & 0xFF), byte((certLength >> 8) & 0xFF), byte((certLength >> 16) & 0xFF), byte((certLength >> 24) & 0xFF)}
// Construct the Blob // Construct the Blob
certBlob := append(certBlobHeader, derBytes...) certBlob := append(certBlobHeader, derBytes...)
@ -99,7 +99,7 @@ func injectCertCryptoApi(derBytes []byte) {
} }
defer certKey.Close() defer certKey.Close()
// Add a magic value which indicates that the certificate is a // Add a magic value which indicates that the certificate is a
// Namecoin cert. This will be used for deleting expired certs. // Namecoin cert. This will be used for deleting expired certs.
// However, we have to delete it before we create it, so that we make sure that the "last modified" metadata gets updated. // However, we have to delete it before we create it, so that we make sure that the "last modified" metadata gets updated.
// If an error occurs during deletion, we ignore it, since it probably just means it wasn't there already. // If an error occurs during deletion, we ignore it, since it probably just means it wasn't there already.
@ -185,7 +185,7 @@ func checkCertExpiredCryptoApi(certStoreKey registry.Key, subKeyName string) (bo
certKeyModTime := certKeyInfo.ModTime() certKeyModTime := certKeyInfo.ModTime()
// If the cert's last modified timestamp differs too much from the current time in either direction, consider it expired // If the cert's last modified timestamp differs too much from the current time in either direction, consider it expired
expired := math.Abs( time.Since(certKeyModTime).Seconds() ) > float64(certExpirePeriod.Value()) expired := math.Abs(time.Since(certKeyModTime).Seconds()) > float64(certExpirePeriod.Value())
return expired, nil return expired, nil
} }

@ -7,7 +7,7 @@ import (
// Injects a certificate by writing to a file. Might be relevant for non-CryptoAPI trust stores. // Injects a certificate by writing to a file. Might be relevant for non-CryptoAPI trust stores.
func injectCertFile(derBytes []byte, fileName string) { func injectCertFile(derBytes []byte, fileName string) {
pemBytes := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) pemBytes := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
err := ioutil.WriteFile(fileName, pemBytes, 0644) err := ioutil.WriteFile(fileName, pemBytes, 0644)
if err != nil { if err != nil {

@ -5,7 +5,7 @@
// Generate a self-signed X.509 certificate for a TLS server. Outputs to // Generate a self-signed X.509 certificate for a TLS server. Outputs to
// 'cert.pem' and 'key.pem' and will overwrite existing files. // 'cert.pem' and 'key.pem' and will overwrite existing files.
// This code has been modified from the stock Go code to generate // This code has been modified from the stock Go code to generate
// "dehydrated certificates", suitable for inclusion in a Namecoin name. // "dehydrated certificates", suitable for inclusion in a Namecoin name.
package main package main
@ -22,12 +22,12 @@ import (
"encoding/pem" "encoding/pem"
"flag" "flag"
"fmt" "fmt"
"github.com/namecoin/ncdns/certdehydrate"
"github.com/namecoin/ncdns/x509"
"log" "log"
"math/big" "math/big"
"os" "os"
"time" "time"
"github.com/namecoin/ncdns/certdehydrate"
"github.com/namecoin/ncdns/x509"
) )
var ( var (
@ -106,19 +106,19 @@ func main() {
fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err) fmt.Fprintf(os.Stderr, "Failed to parse creation date: %s\n", err)
os.Exit(1) os.Exit(1)
} }
var notAfter time.Time var notAfter time.Time
notAfter, err = time.Parse("Jan 2 15:04:05 2006", *validTo) notAfter, err = time.Parse("Jan 2 15:04:05 2006", *validTo)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Failed to parse expiry date: %s\n", err) fmt.Fprintf(os.Stderr, "Failed to parse expiry date: %s\n", err)
os.Exit(1) os.Exit(1)
} }
timestampPrecision := int64(5 * 60) timestampPrecision := int64(5 * 60)
notBeforeFloored := time.Unix( ( notBefore.Unix() / timestampPrecision ) * timestampPrecision, 0 ) notBeforeFloored := time.Unix((notBefore.Unix()/timestampPrecision)*timestampPrecision, 0)
notAfterFloored := time.Unix( ( notAfter.Unix() / timestampPrecision ) * timestampPrecision, 0 ) notAfterFloored := time.Unix((notAfter.Unix()/timestampPrecision)*timestampPrecision, 0)
// Serial components // Serial components
pubkeyBytes, err := x509.MarshalPKIXPublicKey(publicKey(priv)) pubkeyBytes, err := x509.MarshalPKIXPublicKey(publicKey(priv))
if err != nil { if err != nil {
@ -127,12 +127,12 @@ func main() {
pubkeyB64 := base64.StdEncoding.EncodeToString(pubkeyBytes) pubkeyB64 := base64.StdEncoding.EncodeToString(pubkeyBytes)
notBeforeScaled := notBeforeFloored.Unix() / timestampPrecision notBeforeScaled := notBeforeFloored.Unix() / timestampPrecision
notAfterScaled := notAfterFloored.Unix() / timestampPrecision notAfterScaled := notAfterFloored.Unix() / timestampPrecision
// Calculate serial // Calculate serial
serialDehydrated := certdehydrate.DehydratedCertificate { serialDehydrated := certdehydrate.DehydratedCertificate{
PubkeyB64: pubkeyB64, PubkeyB64: pubkeyB64,
NotBeforeScaled: notBeforeScaled, NotBeforeScaled: notBeforeScaled,
NotAfterScaled: notAfterScaled, NotAfterScaled: notAfterScaled,
} }
serialNumber := big.NewInt(1) serialNumber := big.NewInt(1)
serialNumberBytes, err := serialDehydrated.SerialNumber(*host) serialNumberBytes, err := serialDehydrated.SerialNumber(*host)
@ -144,7 +144,7 @@ func main() {
template := x509.Certificate{ template := x509.Certificate{
SerialNumber: serialNumber, SerialNumber: serialNumber,
Subject: pkix.Name{ Subject: pkix.Name{
CommonName: *host, CommonName: *host,
SerialNumber: "Namecoin TLS Certificate", SerialNumber: "Namecoin TLS Certificate",
}, },
NotBefore: notBeforeFloored, NotBefore: notBeforeFloored,
@ -152,7 +152,7 @@ func main() {
// x509.KeyUsageKeyEncipherment is used for RSA key exchange, but not DHE/ECDHE key exchange. Since everyone should be using ECDHE (due to forward secrecy), we disallow x509.KeyUsageKeyEncipherment in our template. // x509.KeyUsageKeyEncipherment is used for RSA key exchange, but not DHE/ECDHE key exchange. Since everyone should be using ECDHE (due to forward secrecy), we disallow x509.KeyUsageKeyEncipherment in our template.
//KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, //KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
KeyUsage: x509.KeyUsageDigitalSignature, KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true, BasicConstraintsValid: true,
} }
@ -180,38 +180,38 @@ func main() {
pem.Encode(keyOut, pemBlockForKey(priv)) pem.Encode(keyOut, pemBlockForKey(priv))
keyOut.Close() keyOut.Close()
log.Print("written key.pem\n") log.Print("written key.pem\n")
parsedResult, err := x509.ParseCertificate(derBytes) parsedResult, err := x509.ParseCertificate(derBytes)
if err != nil { if err != nil {
log.Fatal("failed to parse output cert: ", err) log.Fatal("failed to parse output cert: ", err)
} }
dehydrated, err := certdehydrate.DehydrateCert(parsedResult) dehydrated, err := certdehydrate.DehydrateCert(parsedResult)
if err != nil { if err != nil {
log.Fatal("failed to dehydrate result cert: ", err) log.Fatal("failed to dehydrate result cert: ", err)
} }
rehydrated, err := certdehydrate.RehydrateCert(dehydrated) rehydrated, err := certdehydrate.RehydrateCert(dehydrated)
if err != nil { if err != nil {
log.Fatal("failed to rehydrate result cert: ", err) log.Fatal("failed to rehydrate result cert: ", err)
} }
rehydratedDerBytes, err := certdehydrate.FillRehydratedCertTemplate(*rehydrated, *host) rehydratedDerBytes, err := certdehydrate.FillRehydratedCertTemplate(*rehydrated, *host)
if err != nil { if err != nil {
log.Fatal("failed to fill rehydrated result cert: ", err) log.Fatal("failed to fill rehydrated result cert: ", err)
} }
if ! bytes.Equal(derBytes, rehydratedDerBytes) { if !bytes.Equal(derBytes, rehydratedDerBytes) {
log.Fatal("ERROR: The cert did not rehydrate to an identical form. This is a bug; do not use the generated certificate.") log.Fatal("ERROR: The cert did not rehydrate to an identical form. This is a bug; do not use the generated certificate.")
} }
log.Print("Your Namecoin cert is: {\"d8\":", dehydrated, "}") log.Print("Your Namecoin cert is: {\"d8\":", dehydrated, "}")
log.Print("SUCCESS: The cert rehydrated to an identical form. Place the generated files in your HTTPS server, and place the above JSON in the \"tls\" field for your Namecoin name."); log.Print("SUCCESS: The cert rehydrated to an identical form. Place the generated files in your HTTPS server, and place the above JSON in the \"tls\" field for your Namecoin name.")
if len(*falseHost) > 0 { if len(*falseHost) > 0 {
var falsePriv interface{} var falsePriv interface{}
switch *ecdsaCurve { switch *ecdsaCurve {
case "P224": case "P224":
falsePriv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) falsePriv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
@ -228,32 +228,32 @@ func main() {
if err != nil { if err != nil {
log.Fatalf("failed to generate false private key: %s", err) log.Fatalf("failed to generate false private key: %s", err)
} }
falseSerialNumber := big.NewInt(2) falseSerialNumber := big.NewInt(2)
falseTemplate := x509.Certificate{ falseTemplate := x509.Certificate{
SerialNumber: falseSerialNumber, SerialNumber: falseSerialNumber,
Subject: pkix.Name{ Subject: pkix.Name{
CommonName: *falseHost, CommonName: *falseHost,
SerialNumber: "Namecoin TLS Certificate", SerialNumber: "Namecoin TLS Certificate",
}, },
NotBefore: notBefore, NotBefore: notBefore,
NotAfter: notAfter, NotAfter: notAfter,
// x509.KeyUsageKeyEncipherment is used for RSA key exchange, but not DHE/ECDHE key exchange. Since everyone should be using ECDHE (due to forward secrecy), we disallow x509.KeyUsageKeyEncipherment in our template. // x509.KeyUsageKeyEncipherment is used for RSA key exchange, but not DHE/ECDHE key exchange. Since everyone should be using ECDHE (due to forward secrecy), we disallow x509.KeyUsageKeyEncipherment in our template.
//KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, //KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
KeyUsage: x509.KeyUsageDigitalSignature, KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true, BasicConstraintsValid: true,
} }
falseTemplate.DNSNames = append(falseTemplate.DNSNames, *falseHost) falseTemplate.DNSNames = append(falseTemplate.DNSNames, *falseHost)
falseDerBytes, err := x509.CreateCertificate(rand.Reader, &falseTemplate, &template, publicKey(falsePriv), priv) falseDerBytes, err := x509.CreateCertificate(rand.Reader, &falseTemplate, &template, publicKey(falsePriv), priv)
if err != nil { if err != nil {
log.Fatalf("Failed to create false certificate: %s", err) log.Fatalf("Failed to create false certificate: %s", err)
} }
falseCertOut, err := os.Create("falseCert.pem") falseCertOut, err := os.Create("falseCert.pem")
if err != nil { if err != nil {
log.Fatalf("failed to open falseCert.pem for writing: %s", err) log.Fatalf("failed to open falseCert.pem for writing: %s", err)
@ -261,7 +261,7 @@ func main() {
pem.Encode(falseCertOut, &pem.Block{Type: "CERTIFICATE", Bytes: falseDerBytes}) pem.Encode(falseCertOut, &pem.Block{Type: "CERTIFICATE", Bytes: falseDerBytes})
falseCertOut.Close() falseCertOut.Close()
log.Print("written falseCert.pem\n") log.Print("written falseCert.pem\n")
falseKeyOut, err := os.OpenFile("falseKey.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) falseKeyOut, err := os.OpenFile("falseKey.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil { if err != nil {
log.Print("failed to open falseKey.pem for writing:", err) log.Print("failed to open falseKey.pem for writing:", err)

@ -31,21 +31,21 @@ const defaultTTL = 600
// Therefore when qualifying names in a Value yourself you must check if the // Therefore when qualifying names in a Value yourself you must check if the
// input string is "=" and if so, replace it with "" first. // input string is "=" and if so, replace it with "" first.
type Value struct { type Value struct {
IP []net.IP IP []net.IP
IP6 []net.IP IP6 []net.IP
NS []string NS []string
Alias string Alias string
HasAlias bool // True if Alias was specified. Necessary as "" is a valid relative alias. HasAlias bool // True if Alias was specified. Necessary as "" is a valid relative alias.
Translate string Translate string
HasTranslate bool // True if Translate was specified. Necessary as "" is a valid relative value for Translate. HasTranslate bool // True if Translate was specified. Necessary as "" is a valid relative value for Translate.
DS []*dns.DS DS []*dns.DS
TXT [][]string TXT [][]string
SRV []*dns.SRV SRV []*dns.SRV
Hostmaster string // "hostmaster@example.com" Hostmaster string // "hostmaster@example.com"
MX []*dns.MX // header name is left blank MX []*dns.MX // header name is left blank
TLSA []*dns.TLSA TLSA []*dns.TLSA
TLSAGenerated []x509.Certificate // Certs can be dehydrated in the blockchain, they will be put here without SAN values. SAN must be filled in before use. TLSAGenerated []x509.Certificate // Certs can be dehydrated in the blockchain, they will be put here without SAN values. SAN must be filled in before use.
Map map[string]*Value // may contain and "*", will not contain "" Map map[string]*Value // may contain and "*", will not contain ""
// set if the value is at the top level (alas necessary for relname interpretation) // set if the value is at the top level (alas necessary for relname interpretation)
IsTopLevel bool IsTopLevel bool
@ -249,28 +249,26 @@ func (v *Value) appendSRVs(out []dns.RR, suffix, apexSuffix string) ([]dns.RR, e
return out, nil return out, nil
} }
func (v *Value) appendTLSA(out []dns.RR, suffix, apexSuffix string) ([]dns.RR, error) { func (v *Value) appendTLSA(out []dns.RR, suffix, apexSuffix string) ([]dns.RR, error) {
for _, tlsa := range v.TLSA { for _, tlsa := range v.TLSA {
out = append(out, tlsa) out = append(out, tlsa)
} }
for _, cert := range v.TLSAGenerated { for _, cert := range v.TLSAGenerated {
template := cert template := cert
_, nameNoPort := util.SplitDomainTail(suffix) _, nameNoPort := util.SplitDomainTail(suffix)
_, nameNoPortOrProtocol := util.SplitDomainTail(nameNoPort) _, nameNoPortOrProtocol := util.SplitDomainTail(nameNoPort)
derBytes, err := certdehydrate.FillRehydratedCertTemplate(template, nameNoPortOrProtocol) derBytes, err := certdehydrate.FillRehydratedCertTemplate(template, nameNoPortOrProtocol)
if err != nil { if err != nil {
// TODO: add debug output here // TODO: add debug output here
continue continue
} }
derBytesHex := hex.EncodeToString(derBytes) derBytesHex := hex.EncodeToString(derBytes)
out = append(out, &dns.TLSA{ out = append(out, &dns.TLSA{
Hdr: dns.RR_Header{Name: suffix, Rrtype: dns.TypeTLSA, Class: dns.ClassINET, Hdr: dns.RR_Header{Name: suffix, Rrtype: dns.TypeTLSA, Class: dns.ClassINET,
Ttl: defaultTTL}, Ttl: defaultTTL},
@ -279,9 +277,9 @@ func (v *Value) appendTLSA(out []dns.RR, suffix, apexSuffix string) ([]dns.RR, e
MatchingType: uint8(0), MatchingType: uint8(0),
Certificate: strings.ToUpper(derBytesHex), Certificate: strings.ToUpper(derBytesHex),
}) })
} }
return out, nil return out, nil
} }
@ -854,14 +852,14 @@ func parseTLSADehydrated(tlsa1dehydrated interface{}, v *Value) error {
if err != nil { if err != nil {
return fmt.Errorf("Error parsing dehydrated certificate: %s", err) return fmt.Errorf("Error parsing dehydrated certificate: %s", err)
} }
template, err := certdehydrate.RehydrateCert(dehydrated) template, err := certdehydrate.RehydrateCert(dehydrated)
if err != nil { if err != nil {
return fmt.Errorf("Error rehydrating certificate: %s", err) return fmt.Errorf("Error rehydrating certificate: %s", err)
} }
v.TLSAGenerated = append(v.TLSAGenerated, *template) v.TLSAGenerated = append(v.TLSAGenerated, *template)
return nil return nil
} }
@ -927,7 +925,7 @@ func parseTLSA(rv map[string]interface{}, v *Value, errFunc ErrorFunc) {
var tlsa1m map[string]interface{} var tlsa1m map[string]interface{}
if _, ok := tlsa1.([]interface{}); ok { if _, ok := tlsa1.([]interface{}); ok {
tlsa1m = map[string]interface{} { tlsa1m = map[string]interface{}{
"dane": tlsa1, "dane": tlsa1,
} }
} else { } else {

@ -1,58 +1,57 @@
package tlshook package tlshook
import ( import (
"github.com/hlandau/xlog"
"github.com/namecoin/ncdns/certdehydrate" "github.com/namecoin/ncdns/certdehydrate"
"github.com/namecoin/ncdns/certinject" "github.com/namecoin/ncdns/certinject"
"github.com/namecoin/ncdns/ncdomain" "github.com/namecoin/ncdns/ncdomain"
"github.com/hlandau/xlog"
) )
var log, Log = xlog.New("ncdns.tlshook") var log, Log = xlog.New("ncdns.tlshook")
func DomainValueHookTLS(qname string, ncv *ncdomain.Value) (err error) { func DomainValueHookTLS(qname string, ncv *ncdomain.Value) (err error) {
log.Info("Intercepted a Value for ", qname) log.Info("Intercepted a Value for ", qname)
if protocol, ok := ncv.Map["_tcp"]; ok { // TODO: look into allowing non-TCP protocols if protocol, ok := ncv.Map["_tcp"]; ok { // TODO: look into allowing non-TCP protocols
log.Info("Saw a request with TCP") log.Info("Saw a request with TCP")
if port, ok := protocol.Map["_443"]; ok { // TODO: check all ports, not just 443 if port, ok := protocol.Map["_443"]; ok { // TODO: check all ports, not just 443
log.Info("Saw a request with TCP port 443") log.Info("Saw a request with TCP port 443")
// For dehydrated certificates // For dehydrated certificates
if len(port.TLSAGenerated) > 0 { if len(port.TLSAGenerated) > 0 {
log.Info("Just saw a TLS port 443 capable domain request for ", qname, "!") log.Info("Just saw a TLS port 443 capable domain request for ", qname, "!")
for index, cert := range port.TLSAGenerated { for index, cert := range port.TLSAGenerated {
log.Info("Using dehydrated certificate # ", index) log.Info("Using dehydrated certificate # ", index)
template := cert template := cert
var derBytes []byte var derBytes []byte
derBytes, err = certdehydrate.FillRehydratedCertTemplate(template, qname) derBytes, err = certdehydrate.FillRehydratedCertTemplate(template, qname)
if err != nil { if err != nil {
log.Info("Failed to create certificate: ", err) log.Info("Failed to create certificate: ", err)
continue continue
} }
// TODO: check return value // TODO: check return value
certinject.InjectCert(derBytes) certinject.InjectCert(derBytes)
} }
} }
// TODO: support non-dehydrated certificates // TODO: support non-dehydrated certificates
} }
} }
// remove any certs that aren't valid anymore // remove any certs that aren't valid anymore
certinject.CleanCerts() certinject.CleanCerts()
err = nil err = nil
return return
} }

@ -1,13 +1,13 @@
package tlsrestrictchromium package tlsrestrictchromium
import ( import (
"crypto/sha256"
"encoding/base64" "encoding/base64"
"math/big"
"github.com/miekg/dns"
"encoding/hex" "encoding/hex"
"fmt"
"encoding/json" "encoding/json"
"crypto/sha256" "fmt"
"github.com/miekg/dns"
"math/big"
) )
// DNSHash converts an FQDN to DNS wire format, takes the SHA256 of it, and // DNSHash converts an FQDN to DNS wire format, takes the SHA256 of it, and

@ -1,8 +1,8 @@
package tlsrestrictchromium_test package tlsrestrictchromium_test
import ( import (
"testing"
"github.com/namecoin/ncdns/tlsrestrictchromium" "github.com/namecoin/ncdns/tlsrestrictchromium"
"testing"
) )
func TestDnsHash(t *testing.T) { func TestDnsHash(t *testing.T) {

@ -1,12 +1,12 @@
package main package main
import ( import (
"gopkg.in/hlandau/easyconfig.v1/cflag" "encoding/json"
"github.com/namecoin/ncdns/tlsrestrictchromium"
"gopkg.in/hlandau/easyconfig.v1" "gopkg.in/hlandau/easyconfig.v1"
"gopkg.in/hlandau/easyconfig.v1/cflag"
"io/ioutil" "io/ioutil"
"encoding/json"
"log" "log"
"github.com/namecoin/ncdns/tlsrestrictchromium"
) )
var ( var (

@ -79,7 +79,7 @@ func SplitDomainByFloatingAnchor(qname, anchor string) (subname, basename, rootn
return return
} }
rootname = strings.Join(parts[i:len(parts)], ".") rootname = strings.Join(parts[i:], ".")
basename = parts[i-1] basename = parts[i-1]
subname = strings.Join(parts[0:i-1], ".") subname = strings.Join(parts[0:i-1], ".")
return return

@ -13,13 +13,13 @@ type item struct {
} }
var items = []item{ var items = []item{
item{"", "", "", "", ""}, {"", "", "", "", ""},
item{"a", "a", "", "a", ""}, {"a", "a", "", "a", ""},
item{"alpha", "alpha", "", "alpha", ""}, {"alpha", "alpha", "", "alpha", ""},
item{"alpha.beta", "beta", "alpha", "alpha", "beta"}, {"alpha.beta", "beta", "alpha", "alpha", "beta"},
item{"alpha.beta.gamma", "gamma", "alpha.beta", "alpha", "beta.gamma"}, {"alpha.beta.gamma", "gamma", "alpha.beta", "alpha", "beta.gamma"},
item{"alpha.beta.gamma.delta", "delta", "alpha.beta.gamma", "alpha", "beta.gamma.delta"}, {"alpha.beta.gamma.delta", "delta", "alpha.beta.gamma", "alpha", "beta.gamma.delta"},
item{"alpha.beta.gamma.delta.", "delta", "alpha.beta.gamma", "alpha", "beta.gamma.delta."}, {"alpha.beta.gamma.delta.", "delta", "alpha.beta.gamma", "alpha", "beta.gamma.delta."},
} }
func TestSplitDomainHead(t *testing.T) { func TestSplitDomainHead(t *testing.T) {
@ -51,17 +51,17 @@ type aitem struct {
} }
var aitems = []aitem{ var aitems = []aitem{
aitem{"", "bit", "", "", "", merr.ErrNotInZone}, {"", "bit", "", "", "", merr.ErrNotInZone},
aitem{".", "bit", "", "", "", merr.ErrNotInZone}, {".", "bit", "", "", "", merr.ErrNotInZone},
aitem{"d.", "bit", "", "", "", merr.ErrNotInZone}, {"d.", "bit", "", "", "", merr.ErrNotInZone},
aitem{"a.b.c.d.", "bit", "", "", "", merr.ErrNotInZone}, {"a.b.c.d.", "bit", "", "", "", merr.ErrNotInZone},
aitem{"a.b.c.d.bit.", "bit", "a.b.c", "d", "bit", nil}, {"a.b.c.d.bit.", "bit", "a.b.c", "d", "bit", nil},
aitem{"d.bit.", "bit", "", "d", "bit", nil}, {"d.bit.", "bit", "", "d", "bit", nil},
aitem{"bit.", "bit", "", "", "bit", nil}, {"bit.", "bit", "", "", "bit", nil},
aitem{"bit.x.y.z.", "bit", "", "", "bit.x.y.z", nil}, {"bit.x.y.z.", "bit", "", "", "bit.x.y.z", nil},
aitem{"d.bit.x.y.z.", "bit", "", "d", "bit.x.y.z", nil}, {"d.bit.x.y.z.", "bit", "", "d", "bit.x.y.z", nil},
aitem{"c.d.bit.x.y.z.", "bit", "c", "d", "bit.x.y.z", nil}, {"c.d.bit.x.y.z.", "bit", "c", "d", "bit.x.y.z", nil},
aitem{"a.b.c.d.bit.x.y.z.", "bit", "a.b.c", "d", "bit.x.y.z", nil}, {"a.b.c.d.bit.x.y.z.", "bit", "a.b.c", "d", "bit.x.y.z", nil},
} }
func TestSplitDomainByFloatingAnchor(t *testing.T) { func TestSplitDomainByFloatingAnchor(t *testing.T) {

Loading…
Cancel
Save