$Sir_Login

From m204wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Perform secured web or sockets login

Overview

$Sir_Login is a $function that can be used to perform user logins. It is an unusual $function in several respects:

  • It can only be used during:
    • Janus Web Server or Janus Sockets NEWSESCMD processing
    • VTLAPSY logons from IODEV 7 threads

    Any attempt to use $Sir_Login outside of these two instances 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 they would not want it available on their systems.

    Therefore, to make $Sir_Login available at a Janus Web Server or Janus Sockets site, the following are necessary:

    • $Sir_Login must be requested by the site.
    • A new authorization zap must be applied to the Online load modules, or a new Online load module must be linked from object decks authorized for $Sir_Login.

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

Syntax

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

Syntax terms

%result A numerical result: 0 indicates successful login; 1 indicates failure.
userid The user ID for which to attempt a login. This argument is required and must be non-null. At most sites, all Model 204 user IDs must be all uppercase, so you might need to call $UPCASE to translate this argument to uppercase.
accountid 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 user ID. Again, it may be appropriate in your environment to call $UPCASE to translate this argument to uppercase.
passwd 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 user ID is verified for validity, 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 user ID.

No automatic case translation is performed on this argument. If CUSTOM is not set to 11 (allow mixed-case passwords), you must call $UpCase to translate this argument to uppercase.

Model 204 version 7.6 and earlier: Passwords can be as many as 8 characters long.
Model 204 version 7.7 and later: Passwords can be as many as 127 characters long and can contain special characters and embedded blanks. Leading and trailing blanks, however, are stripped.

newpasswd A new password for the user ID. 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, call $UpCase to translate this argument to uppercase.
  • Model 204 version 7.6 and earlier: Passwords can be as many as 8 characters long.
  • Model 204 version 7.7 and later: Passwords can be as many as 127 characters long.
options A blank-delimited set of option words. These options can be:
GUEST Indicates that the user should be logged on even if the user ID 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 user ID 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 user ID is defined in CCASTAT or the external authorizer database. A NOCHECK login is a trusted login, since for such a login the user ID 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 user ID happens to be defined in CCASTAT or the external authorizer database. Of course this downside might be considered an upside if the user IDs used in a particular $Sir_Login call are independent of user IDs 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 user ID for which the login is done can do subsequent trusted logins by simply typing LOGON (with no user ID) 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.

outlistid 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 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.

Any errors in the arguments such as a null or too-long user ID, 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 user IDs. A connection from a client that contains a certificate signed by that certifying authority can then simply do a trusted login for the user ID 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 user ID, the common name could be mapped to a user ID by 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, for example, a common name, MD5 certificate hash and a Model 204 user ID 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 user ID 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 user ID and password were received a "401 Unauthorized" response can be sent to the client to get a user ID 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 user ID and password suggests that user ID 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 user ID 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 user ID 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 user ID 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 user ID 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 user ID 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 user ID 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 user ID 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 Rocket Software be contacted to review NEWSESCMD code.

Sample APSY

A sample APSY subsystem that can be used with the NEWSESCMD subcommand is provided by Rocket 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.