API: QSYGETPH
は IBM API解説書では「プロファイル・ハンドルの取得」
という表題で紹介されているために、うっかり見逃してしまう API であるが、この API によれば
IBM System i の堅牢なユーザー管理システムを利用できる適用業務を構築することができる。
もう少し簡単に説明してみよう。
例えばC/S (クライアント/サーバー) や Web適用業務においてサイン・オンに代わる
ユーザー認証をどのように作成するか? ということである。
ユーザー認証フォーム(HTML)を作成して、エンド・ユーザーにユーザー名やパスワードを
入力させて フォーム SUBMIT したのでは、入力されたユーザーとパスワードは
そのままの形でTCP/IPストリームとしてインターネット回線を流れていくことになり
第三者の傍受によって、いとも簡単にユーザー,パスワードを盗まれてしまうだろう。
このような脆弱なユーザー認証を防ぐにはやはり System i の堅牢なサイン・オンの
システムを利用するに限ることはいうまでも無い。
5250 エミュレータで利用されているサイン・オンによる認証の仕組みは
ここで紹介する API : QSYGETPH
によって実現することができる。
つまり QSYGETPH
は 5250エミュレータのサインオンの仕組みを再現するための API である。
QSYGETPH とは「プロファイル・ハンドルの取得」という比較的わかりにくい表現で
紹介されているために System i の開発者に利用されている頻度が少ないのではないかと思われる。
「プロファイル・ハンドル」とはユーザー・プロフィールによる環境を構築したときを個別に
識別する識別子のことである。
識別子(ハンドル)とは i5/OS によって重なりのないように自動生成された一意的な値として
生成される。
つまり同じ記号や番号として偶然にも他のものと重なることがないように i5/OS によって
ランダムに発生した記号であり、これによって現在、実行中のユーザー環境を識別するのである。
別の話になるが、あなたも既に自分の Windows PC 上に多くのウィンドウを開いているはずである。
Windows OS は、これらのすべてのウィンドウにやはり「ウィンドウ・ハンドル」と呼ばれる
識別子を持っていて、それらを個別に制御しているのである。
このように複数個、存在する実行中のオブジェクトを識別するための識別子のことを「ハンドル」と呼ぶ。
前置きが長くなってしまったが System i の開発者には「ハンドル」という言葉にはあまり
馴染みがないと思われるので解説した次第である。
仮想ユーザー環境とは QSYGETPH
によってハンドルを取得したときに始まって
QSYRLSPH によってハンドルが解放されるまでのあいだの環境のことである。
つまり QSYGETPH
によってサイン・オンされて QSYRLSPH
によってサイン・オフされると考えてよい。
ここでは API による仮想ユーザー環境の構築と i5/OS リリース別の考慮点についても
現実的で詳細な解説を加えていこうと思う。
必須パラメータ・グループ:
1. | ユーザーID | 入力 | Char(10) |
2. | パスワード | 入力 | Char(*) |
3. | プロファイル・ハンドル | 出力 | Char(12) |
任意選択パラメータ:
4. | エラー・コード | 入出力 | Char(*) |
任意選択パラメータ:
5. | パスワードの長さ | 入力 | Binary(4) |
6. | パスワードの CCSID | 入力 | Binary(4) |
1. ユーザーID
ユーザー・ハンドルを生成する、つまり仮想ログインするユーザー・プロフィールの
10桁の名前。特殊値として *CURRENT
を指定すると現在のユーザー名のハンドルを
取得することができる。
現在のユーザー(*CURRENT
)を取得する理由は、別のユーザーとしてログインしたいときに
現在のユーザーのハンドルを取得しておいてログインしたユーザーを終了したときに
現在のユーザーに戻すために使用する。
2. パスワード
上記で指定するユーザーのパスワード。OS V5R2M0
までは 10桁であるが
V5R3M0
以上では最大128桁までのパスワードを指定することができる。
また特殊値として *NOPWD
とはパスワードがないことを意味する。
例えば HTTP サーバーでの省略時のユーザー : QTMHHTTP
はパスワードを持たないので
*NOPWD
を指定する必要がある。
また QSYS, QDOC, QSPL, QRJE,
... のように、QSYGETPH
を使ってもハンドルの取得で
許されていないユーザーも存在する。
3. プロファイル・ハンドル
QSYGETPH によって自動生成される 12 桁のランダム・ストリングとしての
ユーザー環境を識別するための識別子。
5. パスワードの長さ
OS V5R3M0 以降に追加されたパラメータであり、パスワードの長さの指定である。
このパラメータは任意パラメータとして V5R3M0
から初めて紹介されたが
V5R3M0
では必須パラメータであり、正しく指定していないと QSYGETPH
は
エラーとなって動作しない。これはOS V5R3M0
のバグであり、とうとう最後まで
IBM によって修正されることはなかった。
弊社が原因不明として苦しめられたバグのひとつである。( V5R3M0
はバグの多い問題のあるリリースであった )
IBM は OS Ver5.4 で、このバグを修正して「任意指定パラメータ」のマニュアルの
とおりに指定していなくてもエラーとはしないように正しい動作に改訂されている。
6. パスワードの CCSID
通常では 65535 を指定しておけばよい。
これはユーザーが任意に入力したユーザーで仮想ログインするプログラムである。
特にこの CLP のサンプル・ソースでは面白い例を用意した。
5250 エミュレーターに良く似たサイン・オン画面による仮想ログインのサンプルを
作ってみようというのである。
仮想サイン・オン画面で、ユーザーとパスワードを入力して実行キーを押すと実際のサインオンと
同じ初期プログラムが実行される仕組みを作ろうというのである。
ユーザーの初期プログラムを終了させれば、この仮想サインオンもまたサインオフされる。
このサンプル・ソースの内容を見れば System i のサイン・オンがどのように行なわれているかを
知ることができ、独自の認証システムの構築に造詣を与えてくれるはずである。
0001.00 PGM 0002.00 /*---------------------------------------------------------*/ 0003.00 /* TESTGETPH : QSYGETPH のテスト */ 0004.00 /*---------------------------------------------------------*/ 0005.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(132) 0006.00 DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) 0007.00 DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(132) 0008.00 DCL VAR(&MSGF) TYPE(*CHAR) LEN(10) 0009.00 DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10) 0010.00 DCL VAR(&SBS) TYPE(*CHAR) LEN(20) 0011.00 DCLF FILE(TEST.COM/TESTGETPD) 0012.00 DCL VAR(&OS400) TYPE(*CHAR) LEN(6) 0013.00 DCL VAR(&PRFHND) TYPE(*CHAR) LEN(12) 0014.00 DCL VAR(&APIERR) TYPE(*CHAR) LEN(116) + 0015.00 VALUE(X'000074') /* 2 進数 */ 0016.00 DCL VAR(&NULL4) TYPE(*CHAR) LEN(4) + 0017.00 VALUE(X'00000000') 0018.00 DCL VAR(&PASSLEN) TYPE(*CHAR) LEN(4) + 0019.00 VALUE(X'000A') /* 10 */ 0020.00 DCL VAR(&CCSID) TYPE(*CHAR) LEN(4) + 0021.00 VALUE(X'FFFF') /* 65535 */ 0022.00 DCL VAR(&INLPGM) TYPE(*CHAR) LEN(10) 0023.00 DCL VAR(&INLPGMLIB) TYPE(*CHAR) LEN(10) 0024.00 DCL VAR(&API) TYPE(*CHAR) LEN(10) 0025.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) 0026.00 0027.00 /*(1) OS400 のリリースを検索する */ 0028.00 RTVDTAARA DTAARA(QGPL/QSS1MRI (1 6)) RTNVAR(&OS400) 0029.00 0030.00 /*(2) サイン・オン画面を表示してユーザー、パスワードを受け取る */ 0031.00 CHGVAR VAR(©RIGHT) VALUE('(C) COPYRIGHT OFFICE + 0032.00 QUATTRO 2012-') 0033.00 RTVJOBA JOB(&DEVNAME) 0034.00 RTVSYSVAL SYSVAL(QCTLSBSD) RTNVAR(&SBS) 0035.00 CHGVAR VAR(&SBSNAME) VALUE(%SST(&SBS 1 10)) 0036.00 SNDRCVF RCDFMT(SIGNON) 0037.00 IF COND(&IN03 *EQ '1') THEN(RETURN) 0038.00 0039.00 /*(3) QSYGETPH でログイン・ハンドルを生成する */ 0040.00 IF COND(&OS400 *LT 'V5R3M0') THEN(DO) /* + 0041.00 V5R3M0 未満 */ 0042.00 CALL PGM(QSYGETPH) PARM(&USERID &PASSWRD &PRFHND + 0043.00 &APIERR) 0044.00 ENDDO /* V5R3M0 未満 */ 0045.00 ELSE CMD(DO) /* V5R3M0 以上 */ 0046.00 CHGVAR VAR(%BIN(&PASSLEN)) VALUE(10) 0047.00 CHGVAR VAR(%BIN(&CCSID)) VALUE(65535) 0048.00 CALL PGM(QSYGETPH) PARM(&USERID &PASSWRD &PRFHND + 0049.00 &APIERR &PASSLEN &CCSID) 0050.00 ENDDO /* V5R3M0 以上 */ 0051.00 IF COND(%SST(&APIERR 5 4) *NE &NULL4) THEN(DO) 0052.00 CHGVAR VAR(&API) VALUE('QSYGETPH') 0053.00 GOTO APIERR 0054.00 ENDDO 0055.00 0056.00 /*(4) 指定したユーザーで JOB を開始する */ 0057.00 CALL PGM(QWTSETP) PARM(&PRFHND &APIERR) 0058.00 IF COND(%SST(&APIERR 5 4) *NE &NULL4) THEN(DO) 0059.00 CHGVAR VAR(&API) VALUE('QWTSETP') 0060.00 GOTO APIERR 0061.00 ENDDO 0062.00 0063.00 /*(5) ユーザー・プロフィールで登録されている初期プログラムを起動する */ 0064.00 RTVUSRPRF USRPRF(*CURRENT) INLPGM(&INLPGM) + 0065.00 INLPGMLIB(&INLPGMLIB) 0066.00 CALL PGM(&INLPGMLIB/&INLPGM) 0067.00 0068.00 /*(6) ハンドルを解放して JOB を終了する */ 0069.00 CALL PGM(QSYRLSPH) PARM(&PRFHND) 0070.00 0071.00 RETURN 0072.00 0073.00 APIERR: 0074.00 CHGVAR VAR(&MSGID) VALUE(%SST(&APIERR 9 7)) 0075.00 CHGVAR VAR(&MSGDTA) VALUE(%SST(&APIERR 17 100)) 0076.00 CHGVAR VAR(&MSGF) VALUE('QCPFMSG ') 0077.00 CHGVAR VAR(&MSGFLIB) VALUE('QSYS ') 0078.00 SNDPGMMSG MSG('API: ' *CAT &API *TCAT + 0079.00 ' でエラーがありました。 ') + 0080.00 TOMSGQ(*TOPGMQ) MSGTYPE(*COMP) 0081.00 GOTO SNDERR 0082.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) + 0083.00 MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) + 0084.00 MSGFLIB(&MSGFLIB) 0085.00 SNDERR: IF COND(&MSGID *EQ ' ') THEN(DO) 0086.00 SNDPGMMSG MSG(&MSG) TOMSGQ(*SYSOPR) 0087.00 ENDDO 0088.00 ELSE CMD(DO) 0089.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + 0090.00 MSGDTA(&MSGDTA) TOMSGQ(*TOPGMQ) + 0091.00 MSGTYPE(*ESCAPE) 0092.00 ENDDO 0093.00 ENDPGM
0001.00 A DSPSIZ(24 80 *DS3) 0002.00 A R SIGNON 0003.00 A CF03(03 ' 終了 ') 0004.00 A CLEAR 0005.00 A BLINK 0006.00 A 01 23' 仮想サイン・オン ' 0007.00 A DSPATR(HI) 0008.00 A 02 48' システム . . . . :' 0009.00 A* SYSNAME 8 O 02 70 0010.00 A O 02 70SYSNAME 0011.00 A 03 48' サブシステム . . :' 0012.00 A SBSNAME 10 O 03 70 0013.00 A 04 48' 表示装置 . . . . :' 0014.00 A DEVNAME 10 O 04 70 0015.00 A 06 17' ユーザー . . . . . . . . . . . .' 0016.00 A USERID 10 B 06 53 0017.00 A 07 17' パスワード . . . . . . . . . . .' 0018.00 A PASSWRD 10 I 07 53 0019.00 A DSPATR(ND) 0020.00 A 08 17' プログラム/プロシージャー . . .' 0021.00 A PROGRAM 10 B 08 53CHECK(LC) 0022.00 A 09 17' メニュー . . . . . . . . . . . .' 0023.00 A MENU 10 B 09 53CHECK(LC) 0024.00 A 10 17' 現行ライブラリー . . . . . . . .' 0025.00 A CURLIB 10 B 10 53CHECK(LC) 0026.00 A 99 QSNERROR 80 O 24 01DSPATR(HI) 0027.00 A COPYRIGHT 40 O 24 40DSPATR(HI) 0028.00 A* UBUFFER 128 H
このプログラムは OS V3R7M0 - V5R3M0
, および V5R3M0
以上での動作をカバーしている。
0012.00 DCL VAR(&OS400) TYPE(*CHAR) LEN(6) : 0027.00 /*(1) OS400 のリリースを検索する */ 0028.00 RTVDTAARA DTAARA(QGPL/QSS1MRI (1 6)) RTNVAR(&OS400)
によって QGPL/QSS1MRI *DTAARA
の 1-6 桁に記述されているOS リリースを読み取って、
0039.00 /*(3) QSYGETPH でログイン・ハンドルを生成する */ 0040.00 IF COND(&OS400 *LT 'V5R3M0') THEN(DO) /* + 0041.00 V5R3M0 未満 */ 0042.00 CALL PGM(QSYGETPH) PARM(&USERID &PASSWRD &PRFHND + 0043.00 &APIERR) 0044.00 ENDDO /* V5R3M0 未満 */ 0045.00 ELSE CMD(DO) /* V5R3M0 以上 */ 0046.00 CHGVAR VAR(%BIN(&PASSLEN)) VALUE(10) 0047.00 CHGVAR VAR(%BIN(&CCSID)) VALUE(65535) 0048.00 CALL PGM(QSYGETPH) PARM(&USERID &PASSWRD &PRFHND + 0049.00 &APIERR &PASSLEN &CCSID) 0050.00 ENDDO /* V5R3M0 以上 */ 0051.00 IF COND(%SST(&APIERR 5 4) *NE &NULL4) THEN(DO) 0052.00 CHGVAR VAR(&API) VALUE('QSYGETPH') 0053.00 GOTO APIERR 0054.00 ENDDO
のようにして OS V5R3M0
以上であれば パスワード長つきのパラメータで実行して、それ未満であれば
パスワード長は指定せずに実行する。
これによって
V5R3M0
以降とそれ未満の OS環境の両方をサポートV5R3M0
での OS のバグの回避の両方ともを解決している。
次に QSYGETPH
で取得したハンドルを使って
0056.00 /*(4) 指定したユーザーで JOB を開始する */ 0057.00 CALL PGM(QWTSETP) PARM(&PRFHND &APIERR)
によって仮想ユーザー環境が開始されるので、RTVUSRPRF
を使って次のように
このユーザーの初期プログラムを検索して実行する。
0063.00 /*(5) ユーザー・プロフィールで登録されている初期プログラムを起動する */ 0064.00 RTVUSRPRF USRPRF(*CURRENT) INLPGM(&INLPGM) + 0065.00 INLPGMLIB(&INLPGMLIB) 0066.00 CALL PGM(&INLPGMLIB/&INLPGM)
これでユーザー環境のJOBを開始して実行することができる。
最後にこの JOB を F3=終了 で終了すると仮想環境は終了して
0068.00 /*(6) ハンドルを解放して JOB を終了する */ 0069.00 CALL PGM(QSYRLSPH) PARM(&PRFHND)
によってハンドルを解放して終了する。
このような API : QSYGETPH
を使って仮想ログイン環境を実現できれば
のモデルを構築することができる。
QSYGETPH
に始まる認証API は System i の堅牢な認証システムを使ったユーザー認証に
大いに役立つはずである。