-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
184 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package sig0 | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/miekg/dns" | ||
) | ||
|
||
var ( | ||
SignalSubzonePrefix = "_signal" | ||
DefaultTTL = 300 | ||
DefaultDOHResolver = "dns.quad9.net" | ||
) | ||
|
||
func CreateRequestKeyMsg(subZone, zone string) (*dns.Msg, error) { | ||
|
||
// Determine the zone master using the provided sub zone and base zone | ||
signalZone := fmt.Sprintf("%s.%s", SignalSubzonePrefix, zone) | ||
querySOAForSignal, err := QuerySOA(signalZone) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error: ZONE %s SOA record does not resolve: %w", signalZone, err) | ||
} | ||
|
||
soaAnswer, err := SendDOHQuery(DefaultDOHResolver, querySOAForSignal) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error: DOH query failed for %s: %w", DefaultDOHResolver, err) | ||
} | ||
|
||
zoneSoa, err := ExpectSOA(soaAnswer) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error: SOA record not found in response for %s: %w", signalZone, err) | ||
} | ||
|
||
if zoneSoa != "ns1.free2air.org." { | ||
return nil, fmt.Errorf("Unexpected SOA: %s - TODO: Query SVCB to get the zone master's DOH endpoint", zoneSoa) | ||
} | ||
var dohUpdateURL = "doh.zenr.io" | ||
|
||
// Check if zone already exists | ||
newSubZone := fmt.Sprintf("%s.%s", subZone, zone) | ||
err = checkZoneDoesntExist(dohUpdateURL, newSubZone) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
zoneRequest := fmt.Sprintf("%s.%s.%s", subZone, SignalSubzonePrefix, zone) | ||
err = checkZoneDoesntExist(dohUpdateURL, zoneRequest) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// craft RRs and create signed update | ||
subZoneSigner, err := LoadOrGenerateKey(newSubZone) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
err = subZoneSigner.StartUpdate(zone) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Here we split the key details | ||
keyDetails := strings.TrimSpace(subZoneSigner.Key.String()) | ||
keyFields := strings.Fields(keyDetails) | ||
if len(keyFields) < 6 { | ||
return nil, errors.New("Invalid key data") | ||
} | ||
keyData := strings.Join(keyFields[3:], " ") | ||
|
||
nsupdateItemSig0Key := fmt.Sprintf("%s %d %s", zoneRequest, DefaultTTL, keyData) | ||
err = subZoneSigner.UpdateParsedRR(nsupdateItemSig0Key) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
nsupdateItemPtr := fmt.Sprintf("%s %d IN PTR %s.", newSubZone, DefaultTTL, zoneRequest) | ||
err = subZoneSigner.UpdateParsedRR(nsupdateItemPtr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
signedUpdateMsg, err := subZoneSigner.SignUpdate() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// updateAnswer, err := SendDOHQuery(dohUpdateURL, signedUpdateMsg) | ||
// if err != nil { | ||
// return nil, err | ||
// } | ||
|
||
// if updateAnswer.Rcode != dns.RcodeSuccess { | ||
// return nil, fmt.Errorf("Error: Update failed: %v", updateAnswer) | ||
// } | ||
|
||
return signedUpdateMsg, nil | ||
} | ||
|
||
func checkZoneDoesntExist(dohServer, zone string) error { | ||
doesExistQuery, err := QueryAny(zone) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
doesExistAnswer, err := SendDOHQuery(dohServer, doesExistQuery) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if doesExistAnswer.Rcode != dns.RcodeNameError { | ||
return fmt.Errorf("new zone %s already exists: %v", zone, doesExistAnswer) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package sig0 | ||
|
||
import ( | ||
"crypto/rand" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestRequestKey(t *testing.T) { | ||
r := require.New(t) | ||
|
||
buf := make([]byte, 5) | ||
rand.Read(buf) | ||
testSubZone := fmt.Sprintf("sig0namectl-test-%x", buf) | ||
|
||
zoneRequestMsg, err := CreateRequestKeyMsg(testSubZone, "zenr.io") | ||
r.NoError(err) | ||
t.Log(zoneRequestMsg) | ||
t.FailNow() | ||
|
||
// TODO: cleanup test keys | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters