.title TCPFILTER - filter outgoing TCP accesses .ident /V1.0-1/ ; ; 14-oct-1991 GG v1.0-1 utilisation de deanonpaged plutot que deanonpgdisz ; raz du driver dans unload au cas ou pas unloadable ; 7-oct-1991 GG v1.0: création ; ; programme pour filter les appels TCP sortants ; auteur: guillaume gerard, Telecom PARIS ; ; Ce programme ne permet les connextions sortantes que ; pour les appels sur le reseau local ; la possession de l'identifier UCX$TCP_USER permet ; de sortir vers n'importe quel réseau ; ; le numéro de réseau autorisé est dans la ligne ;#### ; actuellement c'est un réseau classe B, mais il y a peu à changer ; pour le faire marcher sur un autre type de réseau ; .disable global .library /sys$share:lib/ .link @sys$system:sys.stb@/se $ACEDEF $ARMDEF $CHPDEF $DDBDEF $DDTDEF $DPTDEF $DYNDEF $FKBDEF $IODEF $IRPDEF $PCBDEF $SPLCODDEF $SSDEF .page .external sch$iolockr,sch$iounlock,ioc$searchdev .external exe$alonpagvar,exe$abortio,exe$deanonpaged .external exe$fork ; should be in FORK macro! .external exe$chkpro,ioc$gl_dptlist .external lib$put_output ; ; unload code when reloading driver. ; conditional assembly since rather hairy ; we use inittab to store code to call us in case of ; a driver reload, to allow us to leave memory ; UNLOAD=1 ; ; .psect $kernel,rd,wrt,pic,long ; long to allow .align krnlstart: hdr: .quad 0 ; standard hdr ASSUME IRP$W_SIZE,eq,<.-KRNLSTART> krnlallocsz: .blkw 1 ASSUME IRP$B_TYPE,eq,<.-KRNLSTART> .byte DYN$C_BUFIO ; doit être >= 0 pour EXE$DEANONPAGED .byte 0 krnldata: accessfdt:.blkl 1 ; @ of access fdt routine ret_accessfdt: jmp @accessfdt ; never modify from krnlstart to here ; ; FDT routine ; ; inputs IPL 2 ; R0 @FDT ; R3 @IRP ; R4 @PCB ; R5 @UCB ; R6 @CCB ; R7 ; R8 ; AP @Px ; .align long krnlcode: cmpw IRP$W_FUNC(r3),#IO$_ACCESS bneq ret_accessfdt ; P3: internet address descriptor movl 8(ap),r1 ifnord #8,(r1),ret_accessfdt cmpw (r1),#16 bneq ret_accessfdt movl 4(r1),r1 ifnord #16,(r1),ret_accessfdt ; ; R1 --> [port | domain] (bytes inversés) ; [internet addr ] (bytes inversés) ; cmpw 4(r1),#<127> ; 127.0 (loopback) beql ret_accessfdt cmpw 4(r1),#<137+<194@8>> ;#### 137.194 ( mon réseau) beql ret_accessfdt ; we must call directly the system service to remain at IPL 2 pushal chklst calls #1,G^EXE$CHKPRO blbs r0,ret_accessfdt JMP G^EXE$ABORTIO ; ace: .blkb ACE$S_ACEDEF ; parsed ACL .align long chpflags:.long ARM$M_WRITE ; write access objprot:.word ^xFFF0 ; (s:rewd,o,g,w) .align long objowner:.long ^X10004 ; owner SYSTEM (nécessaire pour test SOGW) ; chklst: .word 4,CHP$_ACCESS ; accessor .address chpflags .long 0 .word 2,CHP$_PROT ; object .address objprot .long 0 .word 4,CHP$_OWNER .address objowner .long 0 chpace: .word 0,CHP$_ACL .address ace .long 0 .long 0 ; end of list .page .IF DF,UNLOAD drv_fdtadr: .blkl 1 ; address of pointer of FDT routine drv_unload: .long 0 ; assume no driver unload routine fkb: .blkb fkb$c_length .=fkb+fkb$b_flck .byte SPL$C_IOLOCK8 .=fkb+fkb$c_length ; ; driver unload routine ; ; inputs: IPL$_POWER ; R6 @DDB ; R10 @DPT ; ; we must restore original values for the unload routine ; and the FDT routine, just in case the driver would not unload ; unload_rtn: tstl drv_unload beql 1$ movl drv_unload,-(SP) ; fake rsb subw3 R10,drv_unload,dpt$w_unload(r10); restore driver unload routine brb 2$ 1$: clrw dpt$w_unload(R10) ; clear driver unload routine 2$: movl accessfdt,@drv_fdtadr ; restore original FDT routine address movzbl #SS$_NORMAL,R0 ; fork preserves R0 moval fkb,R5 ; fork block addr FORK ; SMP ok, since we never get back into our code at IPL POWER ; ; note: we can't use COM$DRVDEALMEM since it preserves R0, ; and the driver will not unload since R0 is even ; moval krnlstart,r0 jmp G^EXE$DEANONPAGED ; roule cocotte .ENDC ; krnlend: ; ; krnlsize= .-krnlstart .page ; ; ; .IF DF,UNLOAD .psect rdwrt,rd,wrt instbran: jmp G^SCH$IOLOCKR ; en fait n'importe quoi sauf 1 sym rel instsz= .-instbran .ENDC .psect rdonly,rd,nowrt,long devnam: .ascid /UCX$DEVICE/ idname: .ascid /UCX$TCP_USER/ myacl: .ascid /(IDENTIFIER=UCX$TCP_USER,access=write)/ myace: .long ACE$S_ACEDEF .address ace replace:.ascid /%TCPLOAD-I-REPLACED, previous code replaced./ kernel_inadr: .address mod_accessfdt,- mod_accessfdt_end ; .psect code,rd,nowrt,long,shr,pic .entry main,^m<> $PARSE_ACL_S aclstr=myacl,aclent=myace blbc r0,dehors movzbw ace+ace$b_size,chpace $CMKRNL_S routin=mod_accessfdt cmpl #9,r0 bneq dehors pushal replace calls #1,G^LIB$PUT_OUTPUT dehors: ret .page ; ; translate kernel into system space ; replace ACCESS FDT entry by ours ; ; R4 @PCB ; mod_accessfdt: .word ^M $LKWSET_S inadr=kernel_inadr blbs r0,100$ ret ; 100$: jsb G^SCH$IOLOCKR moval devnam,r1 jsb G^IOC$SEARCHDEV ; search specific device blbc r0,133$ ; ; R1 UCB ; R2 DDB ; R3 SB ; movl DDB$L_DDT(r2),r0 ; @ of DDT movl DDT$L_FDT(r0),R3 ; @ of FDT addl #<16-12>,r3 ; skip over legal & buf mask 1$: addl #12,r3 bbc #IO$_ACCESS,(r3),1$ bsbw find_dpt blbc r0,133$ ; ; first FDT valid for access; replace its entry ; movl 8(r3),accessfdt movl #krnlsize,r1 jsb G^EXE$ALONPAGVAR ; r2 @ allouee ; r1 taille 133$: blbc r0,233$ movw r1,krnlallocsz ; save size pushr #^M ; save R4 for SCH$IOUNLOCK movc3 #krnlsize,krnlstart,(r2) popr #^M ; ; translate $CHKPRO item list ; moval (r2),r0 ; point to $CHKPRO itm list subl3 #krnlstart,r2,r1 10$: tstl (r0) beql 11$ addl r1,4(r0) addl #12,r0 brb 10$ 233$: brb 33$ 11$: .IF DF,UNLOAD movzwl dpt$w_unload(r5),r1 beql 110$ addl r5,r1 movl r1,drv_unload .ENDC ; ; check for replacement ; 110$: bsbw check_replace .IF DF,UNLOAD ; ; since the driver will never use again the INITTAB, we store ; a jmp to our unload routine in its place ; ASSUME INSTSZ,eq,6 subw3 dpt$w_inittab(r5),dpt$w_reinittab(r5),r1 cmpw r1,#instsz bleq 119$ ; no room moval (R2),instbran+2 movzwl dpt$w_inittab(r5),r1 addl r5,r1 movl instbran,(r1)+ movw instbran+4,(r1) movw dpt$w_inittab(r5),dpt$w_unload(r5) moval 8(r3),(r2); save FDT routine pointer addr 119$: .ENDC moval (r2),8(R3) ; update FDT entry tstl r0 beql 3$ ; ; free old kernel fragment ; jsb G^EXE$DEANONPAGED ; R1,R2 destroyed movl #9,r0 ; replaced brb 33$ 3$: movl #1,r0 ; created ; ; save status, unlock io database & return ; 33$: movl r0,-(SP) jsb G^SCH$IOUNLOCK movl (SP)+,r0 ret find_dpt: ; ; inputs R3 @FDT entry ; ; output R0 SS$_BUGCHECK R5=0 ; R0 SS$_NORMAL R5= @DPT ; ; R1 scratch ; ; we find the DPT thinking the FDT address is in its space. ; (the DPT list is locked by the io mutex) ; movl G^IOC$GL_DPTLIST,R5 movl r5,r0 ; end marker 1$: cmpl r3,r5 blssu 10$ ; too low movzwl DPT$W_SIZE(r5),R1 addl R5,R1 ; end of driver cmpl r3,r1 blequ 20$ ; ok 10$: movl DPT$L_FLINK(r5),r5 cmpl r5,r0 bneq 1$ movl #SS$_BUGCHECK,R0 rsb 20$: movzbl #SS$_NORMAL,R0 rsb check_replace: ; ; check for replacement of code ; inputs R3 @ fdt ; R2 @ kernel ; R5 @DPT ; output r0 0: no replacement ; #0: @ of old block ; scratch R1 ; cmpl 8(r3),r5 ; saved FDT rtn addr blssu 1$ movzwl dpt$w_size(R5),R1 addl r5,r1 cmpl 8(r3),r1 blequ 20$ ; FDT routine within the driver. not ours 1$: movl 8(r3),r1 ; assumedly points to krnlcode cmpl (r1),(r2) bneq 10$ .IF DF,UNLOAD cmpw dpt$w_inittab(r5),dpt$w_unload(r5) bneq 10$ movl (r1),(r2) .ENDC ; move original FDT address movl (r1),(r2) moval (r1),r0 10$: rsb 20$: clrl r0 ; no pool marked for dealloc. rsb mod_accessfdt_end: .end main