code wiki / (root) / nx_mcp_authenticated_gate.nx

nx_mcp_authenticated_gate.nx source

↩ module page · 76 lines · 4930 B

1// Fresh native stdio read-only authenticated roundtrip using existing HTTPS fixture. 2// Arguments are executable, base URL, existing capability FILE, expected source bytes. 3// Capability bytes are never printed or copied by this gate. 4import "nx_mcp_https_gate.nx" 5import "nx_cap_mint.nx" 6 7func mag_reply_cap(input:*u8,output:*u8,expected_exp:i64,expected_nonce:i64)->i64 { 8 var file:NxCapFile 9 if cm_file_read(input,&file)!=0{return -1} 10 var parsed:i64=0 11 let v:*NxValue=nx_value_parse_json(file.bytes,file.length,&parsed) 12 if parsed!=NX_VAL_PARSE_OK||v.kind!=NX_VAL_OBJECT{cm_file_close(&file);return -2} 13 var i:i64=0 14 while i<v.n_items{ 15 var j:i64=0;while j<i{ 16 if nx_value_bytes_equal(v.keys_ptr[i],v.key_lens_ptr[i],v.keys_ptr[j],v.key_lens_ptr[j])==1{cm_file_close(&file);return -2};j=j+1 17 };i=i+1 18 } 19 let action:*NxValue=nx_value_object_get(v,"action",6) 20 let allow:*NxValue=nx_value_object_get(v,"allow",5) 21 let token:*NxValue=nx_value_object_get(v,"cap",3) 22 var exp:i64=0;var nonce:i64=0 23 if action==(0 as *NxValue)||allow==(0 as *NxValue)||token==(0 as *NxValue){cm_file_close(&file);return -2} 24 if action.kind!=NX_VAL_STRING||allow.kind!=NX_VAL_STRING||token.kind!=NX_VAL_STRING{cm_file_close(&file);return -2} 25 if nx_value_bytes_equal(action.str_ptr,action.str_len,"MINTED",6)!=1||nx_value_bytes_equal(allow.str_ptr,allow.str_len,"nx_fs",5)!=1{cm_file_close(&file);return -2} 26 if nx_value_object_get_int(v,"exp",3,&exp)!=1||nx_value_object_get_int(v,"nonce",5,&nonce)!=1{cm_file_close(&file);return -2} 27 if exp!=expected_exp||nonce!=expected_nonce||exp<=sys_now_realtime_sec(){cm_file_close(&file);return -3} 28 let capacity:i64=capt_issue_capacity(5,exp,nonce) 29 let payload:*u8=sys_mmap_try(capacity);if payload==(0 as *u8){cm_file_close(&file);return -4} 30 let pn:i64=capt_payload("nx_fs",5,exp,nonce,payload) 31 var valid:i64=token.str_len==capacity&&token.str_ptr[pn]==46 as u8 32 if valid!=0{valid=nx_value_bytes_equal(token.str_ptr,pn,payload,pn)} 33 sys_munmap_direct(payload,capacity) 34 if valid!=1{cm_file_close(&file);return -3} 35 let fd:i64=sys_openat_exclusive(output,MODE_0600) 36 if fd<0{cm_file_close(&file);return -4} 37 var wr:NxFileWriteResult 38 let rc:i64=fio_write_sync_fd(fd,token.str_ptr,token.str_len,&wr) 39 i=0;while i<token.str_len{token.str_ptr[i]=0 as u8;i=i+1} 40 if cm_file_close(&file)!=0{return -4} 41 if rc!=0{return -4} 42 gv_puts("scoped_capability=nx_fs; token_bytes_hidden=1\n") 43 gv_kv("cap_expiry",exp);gv_kv("cap_nonce",nonce) 44 return 0 45} 46 47func main(argc:i64,argv:*i64)->i64 { 48 if argc!=5&&argc!=8{return 2} 49 let c:*i64=gv_ctr() 50 let prefix:*u8=sys_mmap(256);var pos:i64=mpe_cat(prefix,0,"/tmp/nishi-mcp-auth-gate-") 51 pos=mpe_catn(prefix,pos,sys_now_ms());prefix[pos]=0 as u8 52 var credential:*u8=argv[3] as *u8 53 if argc==8{ 54 if mr_equal(argv[5] as *u8,mr_len(argv[5] as *u8),"--mint-response")!=1{return 2} 55 credential=mhg_path(prefix,".scoped.cap") 56 let extract:i64=mag_reply_cap(argv[3] as *u8,credential,cm_atoi(argv[6] as *u8),cm_atoi(argv[7] as *u8)) 57 if extract!=0{gv_kv("private_capability_handoff_error",extract);return 3} 58 } 59 let negative_cap:*u8=mhg_path(prefix,".noncredential") 60 if mhg_file(negative_cap,"nishi-negative-control-not-a-capability\n")!=0{return 2} 61 let request:*u8="{\"jsonrpc\":\"2.0\",\"id\":\"auth-size-a\",\"method\":\"tools/call\",\"params\":{\"name\":\"nx_fs\",\"arguments\":{\"argv\":[\"size\",\"buildroot/runtime/nx_mcp_stdio.nx\"]}}}\n{\"jsonrpc\":\"2.0\",\"id\":\"auth-size-b\",\"method\":\"tools/call\",\"params\":{\"name\":\"nx_fs\",\"arguments\":{\"argv\":[\"size\",\"buildroot/runtime/nx_mcp_stdio.nx\"]}}}\n" 62 let b:*u8=sys_mmap(16384);var n:i64=0 63 let bad_rc:i64=mhg_run(argv[1] as *u8,argv[2] as *u8,mhg_path(prefix,".negative"),negative_cap,request,b,&n) 64 gv_check("noncredential-process-survives",bad_rc==0,c) 65 gv_check("noncredential-does-not-read-source",mhg_lines(b,n)==2&&mhg_has(b,n,"NX-FS-SIZE")==0,c) 66 let good_rc:i64=mhg_run(argv[1] as *u8,argv[2] as *u8,mhg_path(prefix,".authenticated"),credential,request,b,&n) 67 let expected:*u8=sys_mmap(mpe_slen(argv[4] as *u8)+mpe_slen("bytes= exact=1")+1) 68 var at:i64=mpe_cat(expected,0,"bytes=");at=mpe_cat(expected,at,argv[4] as *u8);at=mpe_cat(expected,at," exact=1");expected[at]=0 as u8 69 gv_check("authenticated-process-survives",good_rc==0,c) 70 gv_check("two-complete-correlated-responses",mhg_lines(b,n)==2&&mhg_has(b,n,"\"id\":\"auth-size-a\"")==1&&mhg_has(b,n,"\"id\":\"auth-size-b\"")==1,c) 71 gv_check("actual-source-size-matches",mhg_has(b,n,"NX-FS-SIZE buildroot/runtime/nx_mcp_stdio.nx")==1&&mhg_has(b,n,expected)==1,c) 72 gv_check("no-authenticated-errors",mhg_has(b,n,"\"error\"")==0&&mhg_has(b,n,"\"isError\":true")==0,c) 73 gv_kv("authenticated_response_bytes",n) 74 gv_puts("retained_prefix=");gv_puts(prefix);gv_puts("\n") 75 return gv_verdict("MCP-AUTHENTICATED",c,"Read-only tools/call through fresh exact executable; invalid-capability negative control; capability file stays private.") 76}