首先,贴上两个老贴子的链接,这两位DX都是利用exit program,一个是实现在注释行与非注释行之间的切换,一个是把当前代码行变颜色。
http://bbs.chinaunix.net/viewthread.php?tid=519056&highlight=方便开发的工具
http://www.douzhe.com/docs/bbsjh/5/3930.html
本胖研究了两位DX的程序,大致明白了其中的一些原理,趁今天还不算太忙,与大家分享一下。
首先,400为大家提供了一个exit program的选项(不过太老的版本就没了),也就是一个用户参数,如果在这个选项为某个指定程序的话,那么在编辑环境中(也就是用5或者2去查看修改源代码时),按下热键F7,F8(这个在程序段中,是用CMDKEY='7',或者是cmdkey='8'来判断,和subfile差不多),系统会根据光标所在的位置,取出当前的代码信息,通过指针变量传送,去运行我们指定的程序。
程序的输入输出参数,其实可以认为是三个DS结构,不过是用指针来实现。(指针的意思,和C差不多,总之就是一个地址位,而不是具体的数据。系统给我们的程序传入三个指针,指针所指向的数据结构是固定的)
所以程序中,需要先定义三个指针型的变量(也就是*),然后再定义三个结构体,是based这三个指针的,这样我们就可以象使用其它变量一样,直接使用这三个结构体中的变量,也可以实现对当前代码行(本行)的更改。
下面是简单说明(都是猜的)
三个指针的定义 (名字随便起,不过起得有意义点可以方便阅读)
D PARMSEUINPUT S *
D PARMSEUOUT S *
D PARMSEULINE S *
===============================================================
输入的信息
D D HEADERINFO DS BASED(PARMSEUINPUT) 基于input那个指针的
D RECLENGTH 1 4B 0 行数,这个似乎是固定的
D CURSORRRN 5 8B 0 没看出来。不过在编辑范围围内,值是0001,在SEU(也就是
顶上那条横线那里时,值是0000
D CURSORPOS 9 12B 0 按热键时,光标所在的列数。
D CCSID 13 16B 0
D INRECORDS 17 20B 0 好象是读入的有效代码行数 ?
D MEMBERNAME 21 30 程序名
D FILENAME 31 40 srcfile名
D LIBRARYNAME 41 50 lib名
D MEMBERTYPE 51 60 程序类型(RPGLE、CLP、PF等等)
D CMDKEY 61 61 热键值。如按F7时,就是7;F8时,就是8
D MODE 62 62 我们进入程序的方式。当查看方式进行源代码时,值是B
;修改方式进入时,值是U
D SPLITSESS 63 63 这两个完全不知道。
D RES 64 64
================================================================
返回的信息 (手头上没有资料,不是很明白;不过对照着上面的两个程序看看,应该就是指返回码,
还包含一些代码是否修改的信息标志)
D RETURNINFO DS BASED(PARMSEUOUT)
D RETCODE 1 1
D RES2 2 4
D OUTRECORDS 5 8B 0
D INSERTSEQ 9 15
D RES3 16 37
================================================================
代码信息
D LINEINFO DS BASED(PARMSEULINE)
D LINECMD 1 7 下面这两个没猜出来
D RETURN1 8 20
D TEXT1 21 100 这个重要了,这是当前代码行的具体内容。当我们修改代
码时,就是通过更改这个变量的值,来实现的。
D COMMAND2 101 107 下面这两个也没猜出来,应该是和上面类似的含义
D RETURN 108 120
D TEXT2 121 200 这个是指当前代码行,下面那一行的具体内容。
再来看看第一个程序,利用F7在注释行与非注释行之间切换的程序,原理就是根据不同的程序类型,程序序源码,查看是否有*,如果有,就将其去掉;如果没有,就加上一个*,并将结果返回。
热键取出当前编辑的程序的程序名、FILE名、库名,以及代码内容,可以利用这点,来实现很多我们的功能,比如FTP程序,将注释变色以达到醒目的效果等等
qingzhou 回复于:2006-03-31 13:23:24
标题:
保障系统安全性的一个重要工具 -- 出口程序
说明:
随着对iSeries数据和服务器文件的访问途径前所未有的增加,安全性就越来越成为许多系统管理员关心的一个重要问题。当意识到使用程序继承权限和限制用户能力等方法或者不切实际或者效率不高,管理员们尝试去寻找别的方法来保护系统数据。
管理员们的一个选择就是使用出口程序,出口程序提供安全性和调试功能。其主要特点是使管理员控制用户对数据的访问但无须改变任何系统上的对象的授权。
在您在系统上实施出口程序之前,必须提醒管理员的一点是,保护系统的最好的方法还是为对象设置适当的访问权限,这样能够避免潜在的安全漏洞并确保只有具备权限的用户才能够访问特定的系统对象。
出口程序的好处
出口程序是用于控制用户对服务器可以操作的行为,这些程序可以是由C,CL,RPG语言编写的。随着客户端/服务器结构的计算方式的引进和对Microsoft Access, Query, Internet Information Server (IIS)和其他一些应用的普遍应用,对文件和库的访问可能出现“后门“。当对象级别的授权没有实施的时候,出口程序可以用来监控这些非法访问。
当注册了特定的服务器的出口点,出口程序就可以被激活了。通过OS/400上的注册工具WRKREGING命令就可以简单实现。在大多数情况下,从一个出口点删除了出口程序,那么该服务器作业需要重新启动才会起作用。
通常来说,出口程序不需要非常复杂,它基本上接收一个1字节的返回值和结构,该返回值和结构是在调用的用户,服务器和请求的功能中定义好的特殊结构的数据。这可以使出口程序将返回值设置为1(X‘F1’)来允许访问或者0拒绝访问。相同的程序可以用在不同的服务器和出口点上,但是,您编写的程序必须可以断定哪个服务器将被调用。
如何激活一个出口程序:
1. 创建一个可以接收1个字节返回码并根据返回码来决定接受或者拒绝访问的程序。
2. 将该程序注册到出口点中:使用命令WRKREGINF,选择8。
3. 停止并重新启动相关的服务器作业。
在OS/400上许多出口点是可用的,每一个出口点都对应着特定的服务。例如:AS/400 NetServer和Client Access网络驱动使用的文件服务器所用到的出口点是QIBM_ QPWFS_FILE_SERVE,数据库服务器(ODBC/data transfer/JDBC)有7个出口点。
实施出口程序
为了能够充分演示出口程序的威力,我们首先检查一下在何种状况下来实施出口程序。
在运行应用程序的OS/400系统上最常见的问题就是权限问题,应用程序的权限约定是通过菜单和应用来控制的,在2中情况下,用户通常可以访问所有的库,但是程序限制了用户没有命令行的访问权限。这对于在OS/400的环境下是没有问题的,但是却不能够限制通过ODBC和其他应用程序对系统的访问。
在这样的情况下,出口程序就能够很好地起到作用。问题的关键在于如何确保用户对特定的库和文件没有写的权限并且如何防止对其他文件和库的读取。必须设定一个授权方案来监控特定用户对这些读/写功能的要求。然后由出口程序来决定他们是否可以访问这些请求。这种监控可以是很复杂的,并且通常需要有SQL解析器来确定这些功能的执行。
另一种选择就是拒绝所有的请求或者只允许用户访问特定的库。后者可以通过简单地强制所有连接基于同一用户简要表,并且控制对象权限也基于该用户简要表。出口程序还可以用来将请求服务的用户简要表转换成具备访问权限的默认用户简要表。这样就可以有效地防止那些通过“后门”而没有经过严格访问校验的用户或应用来访问系统,并且,这样的设置不会影响到例如5250会话等其他的功能。
以下是一个用CL编写的出口程序,它接受用户简要表对服务器的请求并将他们转换成只具备有限功能的一般用户简要表,但是,它忽略QSECOFR 或 RJZELLER,允许他们正常的访问。这提供了管理员对单个用户授权的更大的控制权利。
*********************************************************************
0001.00 PGM PARM(&STATUS &REQUEST)
0002.00
0002.01 /******************************************************/
0003.00 /* 通过出口程序来转换用户简要表的例程 */
0003.01 /******************************************************/
0004.00
0005.00 DCL VAR(&STATUS) TYPE(*CHAR) LEN(1) /* ACCEPT OR REJECT */
0006.00 DCL VAR(&REQUEST) TYPE(*CHAR) LEN(2000)
0007.00
0007.01 /******************************************************/
0008.00 /* 变量声明 */
0008.01 /******************************************************/
0009.00
0010.00 DCL VAR(&USER) TYPE(*CHAR) LEN(10)
0011.00 /* DCL VAR(&SRVID) TYPE(*CHAR) LEN(10) */
0012.00 /* DCL VAR(&FMT) TYPE(*CHAR) LEN(8) */
0013.00 DCL VAR(&PHANDLE) TYPE(*CHAR) LEN(12)
0014.00
0014.01 /*****************************************************/
0015.00 /* 从数据结构中提取变量 */
0015.01 /*****************************************************/
0016.00
0017.00 CHGVAR VAR(&STATUS) VALUE('1') /* 将返回值置为1 ,表示接受 */
0018.00 CHGVAR VAR(&USER) VALUE(%SST(&REQUEST 1 10)) /* 从数据结构中提取用户*/
0019.00
0019.01 /*****************************************************/
0020.00 /* 如果用户简要表不是RJZELLER 或 QSECOFR , */
0021.00 /* 获得用户简要表的句柄, */
0022.00 /* 并将用户简要表转换成 RJZTEST */
0022.01 /*****************************************************/
0023.00
0024.00 IF (&USER *EQ 'RJZELLER ') DO /* 不转换该用户简要表 */
0025.00 GOTO CMDLBL(END)
0026.00 ENDDO
0027.00 IF (&USER *EQ 'QSECOFR ') DO /* 不转换该用户简要表 */
0028.00 GOTO CMDLBL(END)
0029.00 ENDDO
0030.00
0031.00 SWAPPRF:
0032.00 CALL QSYS/QSYGETPH PARM('RJZTEST ' 'RJZTEST1 ' &PHANDLE X'00000000')
0033.00 CALL QSYS/QWTSETP PARM(&PHANDLE X'FFFFFFFF')
0034.00 GOTO CMDLBL(END)
0035.00
0036.00 END:
0037.00 ENDPGM
*********************************************************************
程序中第11和12行被注释了,因为在这个例子中只有出口点QIBM_QZDA_INIT被监控。但是,如果不止一个出口点被监控,那么这两行还是有用的。出口点QIBM_QZDA_INIT在服务器初始化和捕捉所有提交的对数据库的用户请求时被调用。
第17行,确保了初始请求不被拒绝(根据程序,其他非‘1’的返回值将全部被拒绝访问)。
第18行,提取了调用该服务的用户名。
第24到第29行确定用户简要表是否需要转换,在该例程中,RJZELLER 和 QSECOFR不需要转换。
第32行使用API提取了为RJZTEST处理用的用户简要表。该参数定义为:
User profile input char(10)
Password input char(10)
Profile Handle output char(12)
Error Code I/O char(*)
第33行使用API QWTSETP来将用户简要表转换成RJZTEST,并根据QSYGETPH将处理转移到 & PHANDLE。该参数定义为:
Profile Handle input char(12)
Error Code I/O char(*)
(注: 这将不会在作业日志中见到类似这样的消息:“Servicing User Profile xxx”,但是,您可以对基于对象加锁来判断作业服务于新用户简要表,新的用户简要表将被列出来,而旧的用户简要表被摘除。)
该程序被每一个服务器例程一个客户端请求调用,也就是说,一个用户的连接不会影响到另一个用户。例如,即使QZDASOINIT被设定为可以重用(MAXUSE大于1),用户RJZELLER也不会被先前BOB用户登陆的连接在断开后所影响。但是,我们还是建议将预启动作业QZDASOINIT, QZDAINIT 和 QZDASSINIT的MAXUSE参数设置为1,来确保当前一个用户断开连接后,其会话信息能够被清除。
有用的备选功能
您可以感觉到,出口程序为系统管理员提供了额外的控制能力,如果基于对象级别的权限总是首先被考虑到的话,那么出口程序的确为其提供了非常有用的备选功能。
其它参考信息
如果您希望了解更多有关出口程序的信息,请阅读“AS/400 Client Access Host Servers” (SC41-5740-03)。
该文档可以从以下的网站上找到:
http://publib.boulder.ibm.com/cgi-bin/bookmgr/BOOKS/QB3AUX03/CCONTENTS?SHELF=QB3AYC05&DN=SC41-5740-03&DT=19990301120241
qingzhou 回复于:2006-03-31 13:29:48
ODBC为异种OS访问AS/400提供接口,但是,安全方面的问题也接踵而来,如何有效监控ODBC对AS/400数据的传输?本文将通过Exit Program的方式来进行监控。
QIBM_QTF_TRANSFER(程序1)
PGM PARM(&RC &STRU)
DCL VAR(&RC) TYPE(*CHAR) LEN(1)
DCL VAR(&STRU) TYPE(*CHAR) LEN(80)
DCL VAR(&USER) TYPE(*CHAR) LEN(10) /* user profile*/
DCL VAR(&APP1) TYPE(*CHAR) LEN(10) /* function */
DCL VAR(&APP2) TYPE(*CHAR) LEN(10) /* sub function*/
DCL VAR(&TFOBJ) TYPE(*CHAR) LEN(10) /* file name */
DCL VAR(&TFLIB) TYPE(*CHAR) LEN(10) /*library */
DCL VAR(&TFMBR) TYPE(*CHAR) LEN(10) /* member */
DCL VAR(&TFFMT) TYPE(*CHAR) LEN(10) /* format */
DCL VAR(&TYPE) TYPE(*CHAR) LEN(2) /* journaltype */
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(EXIT))
CHGVAR &RC VALUE(''1'') /* set return code to +
allow request unless rejected by program */
CHGVAR &USER VALUE(%SST(&STRU 1 10)) /*user */
CHGVAR &APP2 VALUE(%SST(&STRU 21 10)) /*funct*/
CHGVAR &TFOBJ VALUE(%SST(&STRU 31 10)) /*file */
CHGVAR &TFLIB VALUE(%SST(&STRU 41 10)) /*libr */
CHGVAR &TFMBR VALUE(%SST(&STRU 51 10)) /*mbr */
CHGVAR &TFFMT VALUE(%SST(&STRU 61 10)) /*fmt */
LOG: CHGVAR VAR(&TYPE) VALUE(''X'' *CAT &RC)
SNDJRNE JRN(QAUDJRN) TYPE(&TYPE) ENTDTA(&STRU)
EXIT:ENDPGM
QIBM_QZDA_NDB1(程序2)
PGM PARM(&RC &REQUEST)
DCL VAR(&RC) TYPE(*CHAR) LEN(1) VALUE(''1'')
DCL VAR(&REQUEST) TYPE(*CHAR) LEN(700)
DCL VAR(&TYPE) TYPE(*CHAR) LEN(2)
DCL &X1800 *CHAR 4 VALUE(X''00001800'') /*create database file*/
DCL &X1801 *CHAR 4 VALUE(X''00001801'') /*create source file*/
DCL &X1802 *CHAR 4 VALUE(X''00001802'') /*add member */
DCL &X1803 *CHAR 4 VALUE(X''00001803'') /*clear member */
DCL &X1804 *CHAR 4 VALUE(X''00001804'') /*delete member */
DCL &X1805 *CHAR 4 VALUE(X''00001805'') /*file override */
DCL &X1806 *CHAR 4 VALUE(X''00001806'') /*delete file override*/
DCL &X1807 *CHAR 4 VALUE(X''00001807'') /*create save file */
DCL &X1808 *CHAR 4 VALUE(X''00001808'') /*clear save file */
DCL &X1809 *CHAR 4 VALUE(X''00001809'') /*delete file */
/* OPTIMIZED DATABASE SERVER DECLARES */
DCL &DBFMT *CHAR 8 /* format name */
DCL &DBFID *CHAR 4 /* function identifier */
/* FOLLOWING PARAMETERS ADDITIONAL FOR FORMAT ZDAD0100 */
DCL &DBFILE *CHAR 128 /* file name */
DCL &DBLIB *CHAR 10 /* library name */
DCL &DBMBR *CHAR 10 /* member name */
DCL &DBAUT *CHAR 10 /* authority to file */
DCL &DBBFIL *CHAR 128 /* based on file name */
DCL &DBBLIB *CHAR 10 /* based on library name */
DCL &DBOFIL *CHAR 10 /* override file name */
DCL &DBOLIB *CHAR 10 /* override library name */
DCL &DBOMBR *CHAR 10 /* override member name */
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(EXIT))
/* allow request unless rejected by program */
CHGVAR VAR(&RC) VALUE(''1'')
/* set variables from request description */
CHGVAR VAR(&DBFMT) VALUE(%SST(&REQUEST 21 8))
CHGVAR VAR(&DBLIB) VALUE(%SST(&REQUEST 161 10))
CHGVAR VAR(&DBMBR) VALUE(%SST(&REQUEST 171 10))
CHGVAR VAR(&DBOFIL) VALUE(%SST(&REQUEST 329 10))
CHGVAR VAR(&DBOLIB) VALUE(%SST(&REQUEST 339 10))
CHGVAR VAR(&DBOMBR) VALUE(%SST(&REQUEST 349 10))
LOG:
CHGVAR VAR(&TYPE) VALUE(''Z'' *CAT &RC)
SNDJRNE JRN(QAUDJRN) TYPE(&TYPE) ENTDTA(&REQUEST)
EXIT: ENDPGM
☆具体实施方法:
1、将上述2个程序编译,Owner改为QSECOFR,并使用继承权限。
2、CHGNETA PCSACC(*REGFAC)。
3、使用ADDEXITPGM命令把程序添加到相应的Exit point。
4、可以给这2个程序设置一个权限列表,凡是在权限列表内有权限执行此程序的人才可以利用ODBC下传数据
5、用DSPJRN JRN(QAUDJRN) ENTTYP(Z1)就可以查看下传的数据情况了。
6、可以用WRKREGINF查看Exit program设置情况。
注:需要有QAUDJRN,如没有需先WRKSYSVAL修改系统值QAUDCTL、QAUDLVL,然后CRTJRN创建QAUDJRN和创建QAUDJRN。
wildfish 回复于:2006-03-31 13:42:17
:) 还是不太明白Exit Program.
比如我想某个用户QJDBC 对于某个IP段的不能访问?行不行?
|