Skip to content

Commit 6440f7a

Browse files
committed
fix: iterative DB upgrade chain and TXT/CAA quote-stripping on ingress
handleDBUpgrades now loops through all pending versions rather than returning after a single step, so a v0 database correctly runs both handleDBUpgradeTo1 and handleDBUpgradeTo2 before reaching DBVersion 2. stripOuterQuotes() removes any surrounding double-quotes from TXT/CAA values before storage, ensuring the DB always holds raw string content. answerManaged already re-wraps values at serve time, so submitting a pre-quoted value (e.g. '"token"') no longer results in corrupt wire data.
1 parent 360a8ae commit 6440f7a

3 files changed

Lines changed: 42 additions & 8 deletions

File tree

api.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ func toFQDN(name string) string {
2525
return name
2626
}
2727

28+
// stripOuterQuotes removes a single layer of surrounding double-quotes from TXT/CAA values
29+
// so the DB always stores the raw string content regardless of how the caller supplied it.
30+
func stripOuterQuotes(value string) string {
31+
if len(value) >= 2 && value[0] == '"' && value[len(value)-1] == '"' {
32+
return value[1 : len(value)-1]
33+
}
34+
return value
35+
}
36+
2837
// probeRR validates that rtype+value form a parseable DNS RR using a placeholder name and TTL.
2938
func probeRR(rtype, value string) bool {
3039
if rtype == "TXT" || rtype == "CAA" {
@@ -223,7 +232,7 @@ func adminCreateRecord(w http.ResponseWriter, r *http.Request, _ httprouter.Para
223232
ID: uuid.New().String(),
224233
Name: toFQDN(req.Name),
225234
Type: req.Type,
226-
Value: req.Value,
235+
Value: stripOuterQuotes(req.Value),
227236
TTL: ttl,
228237
Created: time.Now().Unix(),
229238
}
@@ -282,7 +291,7 @@ func adminUpdateRecord(w http.ResponseWriter, r *http.Request, ps httprouter.Par
282291
if ttl == 0 {
283292
ttl = 300
284293
}
285-
rec := DNSRecord{ID: id, Name: toFQDN(req.Name), Type: req.Type, Value: req.Value, TTL: ttl}
294+
rec := DNSRecord{ID: id, Name: toFQDN(req.Name), Type: req.Type, Value: stripOuterQuotes(req.Value), TTL: ttl}
286295
if err := DB.UpdateRecord(rec); err != nil {
287296
w.Header().Set("Content-Type", "application/json")
288297
if errors.Is(err, sql.ErrNoRows) {

api_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,22 @@ func TestAdminCreateRecordInvalidMXValue(t *testing.T) {
630630
Expect().Status(http.StatusBadRequest)
631631
}
632632

633+
func TestAdminTXTValueQuoteStripping(t *testing.T) {
634+
_, e := setupAdminRouter(t, "test-token")
635+
// Value submitted with surrounding quotes should be stored and returned without them.
636+
payload := map[string]interface{}{
637+
"name": "txt.example.com",
638+
"type": "TXT",
639+
"value": `"some token"`,
640+
"ttl": 60,
641+
}
642+
obj := e.POST("/admin/records").
643+
WithHeader("Authorization", "Bearer test-token").
644+
WithJSON(payload).
645+
Expect().Status(http.StatusCreated).JSON().Object()
646+
obj.Value("value").String().Equal("some token")
647+
}
648+
633649
func TestAdminListRecordsFilter(t *testing.T) {
634650
_, e := setupAdminRouter(t, "test-token")
635651
// Create an A record and a CNAME record

db.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func (d *acmedb) Init(engine string, connection string) error {
101101
}
102102
if err == nil {
103103
if versionString == "0" {
104-
// No errors so we should now be in version 1
104+
// No errors so we should now be in the current version
105105
insversion := fmt.Sprintf("INSERT INTO acmedns (Name, Value) values('db_version', '%d')", DBVersion)
106106
_, err = db.Exec(insversion)
107107
}
@@ -123,11 +123,20 @@ func (d *acmedb) checkDBUpgrades(versionString string) error {
123123
}
124124

125125
func (d *acmedb) handleDBUpgrades(version int) error {
126-
if version == 0 {
127-
return d.handleDBUpgradeTo1()
128-
}
129-
if version == 1 {
130-
return d.handleDBUpgradeTo2()
126+
for version < DBVersion {
127+
var err error
128+
switch version {
129+
case 0:
130+
err = d.handleDBUpgradeTo1()
131+
case 1:
132+
err = d.handleDBUpgradeTo2()
133+
default:
134+
return nil
135+
}
136+
if err != nil {
137+
return err
138+
}
139+
version++
131140
}
132141
return nil
133142
}

0 commit comments

Comments
 (0)