$Sir_Login

From m204wiki
Revision as of 19:33, 12 April 2013 by JAL (talk | contribs) (→‎Syntax)
Jump to navigation Jump to search

Perform secured web or sockets login

Overview

$Sir_Login is a function that can be used to do user logins in Janus Web Server and Janus Sockets applications. Besides the ability to do user logins, it is an unusual $function in several respects:

  • It can only be run during Janus Web Server or Janus Sockets NEWSESCMD processing. Any attempt to use $Sir_Login outside this will result in request cancellation.
  • It can only be invoked by a non-logged in user. Once a user is logged in, a $Sir_Login call will result in request cancellation
  • While free to all Janus Web Server and Janus Sockets customers, it is implemented as a pseudo-product that requires its own authorization. This is because some sites might view the mere presence of $Sir_Login as a security risk so would not want it available on their systems. So for $Sir_Login to even be made available at a Janus Web Server or Janus Sockets site, it must be requested by the site, and a new authorization ZAP must be applied to the Online load modules, or a new Online load module should be linked from object decks authorized for $Sir_Login.

Syntax

%result = $Sir_Login(userid, [accountid], [passwd], [newpasswd], [options], [outlistid])

%result is set to 0 to indicate successful login or 1 to indicate failure.

$Sir_Login accepts six arguments and returns either a 0 to indicate a successful login or a 1 to indicate login failure.

  • The first argument is the userid for which to attempt a login. This argument is required and must be non-null. At least for 3270 users, all Model 204 user IDs must be all uppercase, so you may need to call $UPCASE to translate this argument to uppercase.
  • The second argument is the account ID to be used for a successful login. This argument is optional and, if not specified, the account ID is set to the same value as the userid. Again, it may be appropriate in your environment to call $UPCASE to translate this argument to uppercase.
  • The third argument is the password to be used for user authentication. This is an optional argument; if it is not specified or null, a trusted login is performed: the userid is verified as a valid userid, and if it is valid, the user is logged in without a password check. Obviously, not specifying this argument or specifying it as null should only be done when the application can be certain that the end-user is authorized to access the userid. At least for 3270 users, all Model 204 user passwords must be all uppercase, so you may need to call $UpCase to translate this argument to uppercase.
  • The fourth argument is a new password for the userid. This is an optional argument, and if it is not specified or null, no new password is set on a successful login. If the third argument is null, this argument is ignored. If you want to ensure that the Model 204 user password is all uppercase, you may need to call $UpCase to translate this argument to uppercase.
  • The fifth argument is a blank-delimited set of option words. These options can be
    GUEST Indicates that the user should be logged on even if the userid in the first $Sir_Login argument is not in CCASTAT or the external authorizer database. A GUEST login is a trusted login, since for such a login the userid is not defined anywhere that would have a password associated with it.

    The NEWSESGUESTOK parameter must be specified on the Janus port definition if the GUEST option is used with $Sir_Login.

    NOCHECK Indicates that the user should be logged in without checking to see if the userid is defined in CCASTAT or the external authorizer database. A NOCHECK login is a trusted login, since for such a login the userid is not looked up anywhere so there's no password to check. NOCHECK is similar to GUEST with the exception that NOCHECK doesn't even bother to do a lookup for the user. This means a NOCHECK login is more efficient than a GUEST login, especially if an external authorizer is being used. The downside is that with a NOCHECK login, the user cannot pick up additional privileges if the userid happens to be defined in CCASTAT or the external authorizer database. Of course this downside might be considered an upside if the userids used in a particular $Sir_Login call are independent of userids in CCASTAT or the external authorizer database.

    The NEWSESGUESTOK parameter must be specified on the Janus port definition if the NOCHECK option is used with $Sir_Login.

    TRUST Indicates that the userid for which the login is done can do subsequent trusted logins by simply typing LOGON (with no userid) on the Model 204 command line.

    This feature is probably most useful in a development Online where end-users have access to the Model 204 command line and might want to do a quick logon/logoff sequence to reset everything. Simply being able to type LOGON eliminates the need for re-entering a password, so it makes quick logon/logoffs much simpler than it would be otherwise. And since the user already logged on to the thread once, there is no security hole in doing a subsequent trusted login. This parameter is only allowed for applications running on a TNSERV port, and like TNSERV ports, it is only available in Sirius Mods version 6.9 and later.

  • The sixth argument is the $list identifier of a $list to receive any terminal messages issued during the login process. These could be error messages during a failed login or information messages issued for a successful login. This is an optional parameter; if it is not specified, messages get sent to the standard output drivers, which could:
    • In a Janus Web Server $Sir_Login, send the output to the browser or the audit trail, or simply swallow it.
    • In a Janus Sockets $Sir_Login, send the output to the audit trail or to one or more open sockets.
    • In either a Janus Web Server or a Janus Sockets $Sir_Login, capture terminal output to a $list via $List_Capture. If $Sir_Login is invoked with an output $list, the X'06' bits of the Model 204 MSGCTL user parameter are automatically cleared, then restored upon completion of $Sir_Login processing. This ensures that logon messages are sent to the "terminal" and so the output $list, no matter what the current MSGCTL setting is. APSY subsystems that suppress messages do so by setting one or both of the MSGCTL X'06' bits. $LIST_CAPTURE does not affect the MSGCTL setting. For more information about $lists, see the Sirius Functions Reference Manual.

Any errors in the arguments such as a null or too-long userid, a too-long password, or an invalid $list identifier cause request cancellation.

Usage notes and examples

Note: It cannot be overemphasized that before $Sir_Login is called, the password should be checked for a null value, unless the intent is to do a trusted login. Without such a check, unauthorized users can log in to an ID without that ID's password.

Trusted Login

Trusted logins should be limited to cases where you are certain that the correct userid can be ascertained without the use of a password. In general, this can only really be done with TCP/IP with the use of certificates, though there might be cases where network and operating system configuration allows you to be certain that a userid that is passed over a connection is valid and trustworthy without a password.

Another case where trusted logins might be reasonable is when a password is retrieved from a connection, and the password is validated against a non-CCASTAT, non-external authorizer database. This database could be a Model 204 file that contains one-way encrypted passwords (saving unencrypted passwords is a very bad idea), or perhaps a database on another machine, such as an LDAP server which is queried via a Janus Sockets client request.

Protected Access and External Authorizers

One simple way to use certificates for login validation is by having a local certifying authority that gives users certificates that contain their userids. A connection from a client that contains a certificate signed by that certifying authority can them simply do a trusted login for the userid passed in the common name portion of the certificate, on the theory that only the user in the certificate would have access to the signed certificate.

The following is a fragment of code from a Janus Web Server NEWSESCMD request that illustrates this technique:

IF $WEB_CERT_INFO('CNAME', 1) EQ 'Trusted CA' THEN %USERID = $WEB_CERT_INFO('CNAME') %RC = $Sir_Login(%USERID) IF NOT %RC THEN STOP END IF ...

A Janus Sockets server NEWSESCMD request that accomplishes the same thing is virtually identical (whether using a $function, as below, or using a comparable Socket object method):

IF $SOCK_CERT_INFO(1, 'CNAME', 1) EQ 'Trusted CA' THEN %USERID = $SOCK_CERT_INFO(1, 'CNAME') %RC = $Sir_Login(%USERID) IF NOT %RC THEN STOP END IF ....

Both these examples depend on the following:

  • A trusted certifying authority certificate with a common name of "Trusted CA" must be added to the appropriate port with the JANUS ADDCA command.
  • Only a single trusted CA with the indicated common name must exist. While it's unlikely that one would have trusted CA certificates for multiple certifying authorities with the same common name, this issue should still be kept in mind.

More sophisticated and complex approaches to client-certificate based user validation can be implemented using the same few $functions or object methods. For example, rather than using the common name in a certificate directly as a userid, the common name could be mapped to a userid via a database lookup:

IF $WEB_CERT_INFO('CNAME', 1) EQ 'Trusted CA' THEN %CNAME = $WEB_CERT_INFO('CNAME') F: IN FILE USERS FD CNAME EQ %CNAME END FIND FOR 1 RECORD IN F %RC = $Sir_Login(USERID) IF NOT %RC THEN STOP END IF . . . .

An even more sophisticated NEWSESCMD application could itself maintain the USERS file that contains say a common name, MD5 certificate hash and a Model 204 userid associated with the certificate. When a certificate is received, the common name and MD5 hash can be looked up in the database:

%CNAME = $WEB_CERT_INFO('CNAME') %MD5HASH = $WEB_CERT_INFO('MD5HASH') F: IN FILE USERS FD CNAME EQ %CNAME MD5HASH EQ %MD5HASH END FIND FOR 1 RECORD IN F %RC = $Sir_Login(USERID) IF NOT %RC THEN STOP END IF END FOR . . . .

If the received certificate is not in the database, the userid and password could be obtained from HTTP headers and could be used for a logon attempt with a password. If the login fails or no userid and password were received a "401 Unauthorized" response can be sent to the client to get a userid and password:

%USERID = $WEB_USER %PASSWORD = $WEB_PASSWORD IF %USERID NE '' AND %PASSWORD NE '' THEN %RC = $Sir_Login(%USERID, %PASSWORD) IF NOT %RC THEN JUMP TO SUCCESS END IF END IF %RC = $WEB_DONE(401, 'Unauthorized') STOP . . . .

$Web_Password, like $Sir_Login, causes request cancellation if used outside of NEWSESCMD processing.

Finally, a successful login for a specific userid and password suggests that userid is the holder of the indicated certificate, so the certificate information can be saved in the USERS database for subsequent trusted logins:

SUCCESS: IN FILE USERS STORE RECORD CNAME = %CNAME MD5HASH = %MD5HASH USERID = %USERID END STORE STOP

Note that in the preceding example, it does not matter which certifying authority signed the user's certificate, as long as it was a certifying authority added to the port via the JANUS ADDCA command.

A similar technique can be used with Janus Sockets, though, of course, when a certificate is not in the database, the userid and password need to be extracted in some way other than via $Web_User and $Web_Pass. The appropriate technique would largely depend on the protocol being used over TCP/IP.

Telnet Example

The following illustrates how a userid and password can be obtained from a user when using the telnet protocol over a Janus Sockets connection:

REPEAT FOREVER %RC = $SOCK_SEND(1, 'Userid: ') %RC = $SOCK_RECVPRS(1, %DATA, 9999999) %USERID = $UPCASE(%DATA) IF %USERID NE '' THEN %RC = $SOCK_SEND(1, 'Password: ') %RC = $SOCK_RECVPRS(1, %DATA, 9999999) %PASSWORD = $UPCASE(%DATA) END IF IF %PASSWORD NE '' THEN %LIST = $LISTNEW %LOGIN = $Sir_Login(%USERID, ,%PASSWORD, , ,%LIST) FOR %I FROM 1 TO $LISTCNT(%LIST) %RC = $SOCK_SENDLN(1, $LISTINF(%LIST, %I)) END FOR IF NOT %LOGIN THEN LOOP END END IF END IF %RC = $SOCK_SENDLN(1, 'Login failed') END REPEAT

Again, this kind of approach can be combined with a certificate-based approach where, if a received certificate is in the database, no userid and password prompting is done, and a trusted login is performed.

Proxy Servers

Another use of $Sir_Login might be a case where all user validation is performed by a proxy server at a well known IP address. The network and proxy server machine are securely configured in such a way that, if Janus Web Server receives a request from a specific IP address, it can be certain of these:

  • The request is coming from the proxy server.
  • The proxy server has performed appropriate user validation for the request.

Finally, the proxy server in question is known to place the validated userid into a nonstandard HTTP header parameter called "Userid". The following illustrates how a trusted login can be performed in such a situation:

IF $WEB_IPADDR EQ %PROXY_IPADDR THEN %USERID = $UPCASE($WEB_HDR_PARM('USERID')) IF %USERID NE '' THEN %RC = $Sir_Login(%USERID) IF NOT %RC THEN STOP END IF . . . .

In this example, the $Sir_Login will still fail if the userid received from the proxy server is defined neither with the external authorizer nor in CCASTAT. If, as is likely, it is undesirable to try to maintain the user lists in both the proxy server and in the external authorizer or CCASTAT, a guest login can be performed with $Sir_Login:

IF $WEB_IPADDR EQ %PROXY_IPADDR THEN %USERID = $UPCASE($WEB_HDR_PARM('USERID')) IF %USERID NE '' THEN %RC = $Sir_Login(%USERID, , , , 'GUEST') IF NOT %RC THEN STOP END IF . . . .

In this case, the user will pick up default user privileges for the Online but will run under the userid passed by the proxy server, even when the user is not defined in CCASTAT or to the external authorizer. This can be very useful for user tracking and auditing and for web-rule-based or APSY-based user access control.

If there are web-based DBA or system manager applications out there that one would not expect to be accessed through the proxy server, it might be worth making sure that the proxy server did not pass the userid of a DBA or system manager who might have access to these critical applications:

IF $WEB_IPADDR EQ %PROXY_IPADDR THEN %USERID = $UPCASE($WEB_HDR_PARM('USERID')) IF $WINDEX('DBA SUPERKLUGE ZEUS', %USERID) THEN AUDIT 'Received userid ' %USERID 'from proxy server' %RC = $WEB_DONE(403, 'Forbidden') STOP END IF . . . .

The combination of $Sir_Login and NEWSESCMD processing provides a very flexible set of facilities that allows a site to tailor Janus Web Server and Janus Sockets user authentication as needed. With that flexibility comes the responsibility to ensure that the chosen user authentication approach is, indeed, secure. Toward this end, it is strongly recommended that NEWSESCMD code be examined by as many eyes as is reasonable, and that Sirius Software be contacted to review NEWSESCMD code.

Sample APSY

A sample APSY subsystem that can be used with the NEWSESCMD subcommand is provided by Sirius Software (it is the same sample subsystem provided for use with the VTLAPSY parameter for IODEV7 users). The code is in the SIRIUS file, beginning with UL/SPF Version 7.7. Programs are VTLN.LOGIN and VTLN.ERROR, and the comments in VTLN.LOGIN explain how to customize the programs for the local environment.