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}