code wiki / _hdl_build / nx_porkbun_dnssec_check.nx
nx_porkbun_dnssec_check.nx source
↩ module page · 72 lines · 4445 B
1// nx_porkbun_dnssec_check.nx -- ask PORKBUN (the actual authority, over the sovereign TLS-1.2 client;
2// NO third-party resolver) whether DNSSEC is enabled on a domain, and PRINT the raw record set. Compares
3// the broken domain against the KNOWN-GOOD one: if andelinwest.com has DNSSEC and nishifamily.com does
4// not (or has a mismatched DS), that is why andelinwest "resolves on some networks, not others" while
5// nishifamily works everywhere -- DNSSEC-validating resolvers SERVFAIL a domain with a bad DS.
6// usage: nx_porkbun_dnssec_check <domain> [<domain> ...] (default: andelinwest.com nishifamily.com)
7// (run nx_secret_cli get porkbun first -> /tmp/nxsecret.out) license_tier: ORIGINAL
8import "nx_acme_porkbun.nx"
9const K_MAGIC_65536: i64 = 65536
10const K_MAGIC_4194304: i64 = 4194304
11
12func dc_pp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
13func dc_pe(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(2,s,n); return 0 }
14func dc_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
15func dc_contains(hay: *u8, n: i64, needle: *u8) -> i64 {
16 let nl: i64 = dc_slen(needle); if nl==0 { return 0 }
17 var i: i64=0
18 while i+nl<=n { var m: i64=1; var j: i64=0; while j<nl { if (hay[i+j] as i64)!=(needle[j] as i64) { m=0; j=nl } else { j=j+1 } } if m==1 { return 1 } i=i+1 }
19 return 0
20}
21
22func dc_creds(ak: *i64, akn: *i64, sk: *i64, skn: *i64) -> i64 {
23 let raw: *u8 = sys_mmap(512)
24 let rawn: i64 = pk_readline_file("/tmp/nxsecret.out\x00" as *u8, raw, 512)
25 if rawn <= 0 { return 0 }
26 var base: i64 = 0
27 if rawn >= 3 { if (raw[0] as i64)==0xef { if (raw[1] as i64)==0xbb { if (raw[2] as i64)==0xbf { base=3 } } } }
28 var nl: i64 = base
29 while nl < rawn { if (raw[nl] as i64)==0x0a { break } nl=nl+1 }
30 ak[0] = (raw + base) as i64; akn[0] = nl - base
31 var s2: i64 = nl + 1
32 var nl2: i64 = s2
33 while nl2 < rawn { if (raw[nl2] as i64)==0x0a { break } nl2=nl2+1 }
34 sk[0] = (raw + s2) as i64; skn[0] = nl2 - s2
35 return 1
36}
37
38func dc_one(store: *TrustStore, now: i64, ak: *u8, akn: i64, sk: *u8, skn: i64, domain: *u8) -> i64 {
39 let dn: i64 = dc_slen(domain)
40 let resp: *u8 = sys_mmap(K_MAGIC_65536)
41 let rn: *i64 = sys_mmap(8) as *i64
42 dc_pp(" " as *u8); dc_pp(domain); dc_pp(": " as *u8)
43 let rc: i64 = nx_porkbun_get_dnssec(ak, akn, sk, skn, domain, dn, store, now, resp, K_MAGIC_65536, rn)
44 if rc != NX_PORKBUN_OK { dc_pp("API-ERROR (rc=" as *u8); let c: *u8=sys_mmap(4); c[0]=(48+rc) as u8; sys_write(1,c,1); dc_pp(")\n" as *u8); return 0 }
45 // Find the body (after the header). Look for "records": and whether it has content.
46 // Porkbun returns {"status":"SUCCESS","records":{...}} -- empty {} = NO DNSSEC; keyTag/digest = ENABLED.
47 if dc_contains(resp, rn[0], "keyTag" as *u8) == 1 { dc_pp("DNSSEC = ENABLED (has DS/keyTag) <== a broken/mismatched DS here breaks validating resolvers\n" as *u8) }
48 else { if dc_contains(resp, rn[0], "\"records\":{}" as *u8) == 1 { dc_pp("DNSSEC = OFF (empty record set)\n" as *u8) }
49 else { if dc_contains(resp, rn[0], "\"records\":[]" as *u8) == 1 { dc_pp("DNSSEC = OFF (empty record set)\n" as *u8) }
50 else { dc_pp("DNSSEC = (inspect raw) -> " as *u8); sys_write(1, resp, rn[0]); dc_pp("\n" as *u8) } } }
51 return 0
52}
53
54func main(argc: i64, argv: *i64) -> i64 {
55 dc_pp("=== nx_porkbun_dnssec_check: DNSSEC status straight from Porkbun (no third-party resolver) ===\n" as *u8)
56 let lr: i64 = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt\x00" as *u8, 300, K_MAGIC_4194304)
57 if lr <= 0 { dc_pe("trust load FAIL\n" as *u8); return 1 }
58 let store: *TrustStore = lr as *TrustStore
59 let now: i64 = sys_now_realtime_sec()
60 let akb: *i64 = sys_mmap(8) as *i64; let aknb: *i64 = sys_mmap(8) as *i64
61 let skb: *i64 = sys_mmap(8) as *i64; let sknb: *i64 = sys_mmap(8) as *i64
62 if dc_creds(akb, aknb, skb, sknb) != 1 { dc_pe("creds read FAIL -- run nx_secret_cli get porkbun first\n" as *u8); return 2 }
63 let ak: *u8 = akb[0] as *u8; let sk: *u8 = skb[0] as *u8
64 if argc > 1 {
65 var i: i64 = 1
66 while i < argc { dc_one(store, now, ak, aknb[0], sk, sknb[0], argv[i] as *u8); i = i + 1 }
67 return 0
68 }
69 dc_one(store, now, ak, aknb[0], sk, sknb[0], "andelinwest.com" as *u8)
70 dc_one(store, now, ak, aknb[0], sk, sknb[0], "nishifamily.com" as *u8)
71 return 0
72}