$Sir Login: Difference between revisions
m (1 revision) |
|||
(57 intermediate revisions by 9 users not shown) | |||
Line 1: | Line 1: | ||
{{DISPLAYTITLE:$ | {{DISPLAYTITLE:$Sir_Login}} | ||
<span class="pageSubtitle" | <span class="pageSubtitle">Perform secured web or sockets login</span> | ||
==Overview== | ==Overview== | ||
<var>$Sir_Login</var> is a $function that can be used to perform user logins. It is an unusual $function in several respects: | |||
<ul> | |||
<li>It can only be used during: | |||
<ul> | |||
<li><var class="product">Janus Web Server</var> or <var class="product">Janus Sockets</var> <var>[[NEWSESCMD]]</var> processing </li> | |||
<li> <var>[[VTLAPSY parameter|VTLAPSY]]</VAR> logons from <var>IODEV</var> 7 threads </li> | |||
</ul> | |||
<p> | |||
Any attempt to use <var>$Sir_Login</var> outside of these two instances will result in request cancellation. </p></li> | |||
<li>It can only be invoked by a non-logged in user. Once a user is logged in, a <var>$Sir_Login</var> call will result in request cancellation. </li> | |||
<li>While free to all <var class="product">Janus Web Server</var> and <var class="product">Janus Sockets</var> customers, it is implemented as a pseudo-product that requires its own authorization. This is because some sites might view the mere presence of <var>$Sir_Login</var> as a security risk, so they would not want it available on their systems. | |||
<p> | |||
Therefore, to make <var>$Sir_Login</var> available at a <var class="product">Janus Web Server</var> or <var class="product">Janus Sockets</var> site, the following are necessary: </p> | |||
<ul> | <ul> | ||
<li> | <li><var>$Sir_Login</var> must be requested by the site. </li> | ||
<li>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 <var>$Sir_Login</var>. </li> | |||
</ul> | |||
</ul> | </ul> | ||
<var>$Sir_Login</var> accepts six arguments and returns a 0 to indicate a successful login or a 1 to indicate login failure. | |||
==Syntax== | ==Syntax== | ||
<p class="syntax"><span class="term">%result </span><span class="literal">= $Sir_Login(</span><span class="term">userid, accountid, passwd, newpasswd, options, outlistid</span><span class="literal">)</span> | <p class="syntax"><span class="term">%result </span><span class="literal">= $Sir_Login(</span><span class="term">userid</span>, [<span class="term">accountid</span>], [<span class="term">passwd</span>], [<span class="term">newpasswd</span>], [<span class="term">options</span>], [<span class="term">outlistid</span>]<span class="literal">)</span> | ||
</p> | </p> | ||
%result | ===Syntax terms=== | ||
<table> | |||
<tr><th>%result</th> | |||
<td>A numerical result: 0 indicates successful login; 1 indicates failure. </td> | |||
<tr><th>userid</th> | |||
<td>The user ID for which to attempt a login. This argument is required and must be non-null. At most sites, all <var class="product">Model 204</var> user IDs must be all uppercase, so you might need to call <var>$UPCASE</var> to translate this argument to uppercase. </td></tr> | |||
<tr><th>accountid</th> | |||
<td>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 <var>$UPCASE</var> to translate this argument to uppercase. </td></tr> | |||
<tr><th>passwd</th> | |||
<td>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. | |||
<p> | |||
No automatic case translation is performed on this argument. If <var>[[CUSTOM parameter#Using CUSTOM=(11)|CUSTOM]]</var> is <b>not</b> set to 11 (allow mixed-case passwords), you must call <var>$UpCase</var> to translate this argument to uppercase. </p> | |||
<p> | |||
Model 204 version 7.6 and earlier: Passwords can be as many as 8 characters long. <br /> | |||
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. </p></td></tr> | |||
<tr><th>newpasswd</th> | |||
<td>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 <var class="product">Model 204</var> user password is all uppercase, call <var>$UpCase</var> to translate this argument to uppercase. | |||
<ul> | <ul> | ||
<li | <li>Model 204 version 7.6 and earlier: Passwords can be as many as 8 characters long. </li> | ||
< | <li>Model 204 version 7.7 and later: Passwords can be as many as 127 characters long. </li> | ||
< | </ul></td></tr> | ||
<tr><th>options</th> | |||
< | <td>A blank-delimited set of option words. These options can be: | ||
<tr><th><var> | <table> | ||
<tr><th><var>GUEST</var></th> | |||
<td>Indicates that the user should be logged on even if the user ID in the first <var>$Sir_Login</var> 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. | |||
<p> | |||
The <var>[[NEWSESGUESTOK]]</var> parameter must be specified on the Janus port definition if the GUEST option is used with <var>$Sir_Login</var>.</p></td></tr> | |||
The <var>NEWSESGUESTOK</var> parameter must be specified on the Janus port definition if the <var>NOCHECK</var> option is used with $ | <tr><th><var>NOCHECK</var></th> | ||
</td></tr> | <td>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. | ||
<p> | |||
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 <var>$Sir_Login</var> call are independent of user IDs in CCASTAT or the external authorizer database.</p> | |||
<p> | |||
The <var>NEWSESGUESTOK</var> parameter must be specified on the Janus port definition if the <var>NOCHECK</var> option is used with <var>$Sir_Login</var>.</p></td></tr> | |||
<tr><th><var>TRUST</var></th><td>Indicates that the | <tr><th><var>TRUST</var></th> | ||
<td>Indicates that the user ID for which the login is done can do subsequent trusted logins by simply typing <code>LOGON</code> (with no user ID) on the <var class="product">Model 204</var> command line. | |||
This feature is probably most useful in a development Online where end | <p> | ||
want to do a quick logon/logoff sequence to reset everything. Simply being able to type LOGON eliminates the need for re-entering a | This feature is probably most useful in a development Online where end users have access to the <var class="product">Model 204</var> command line and might want to do a quick logon/logoff sequence to reset everything. Simply being able to type <code>LOGON</code> 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 | 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.</p> | ||
<p> | |||
This parameter is only allowed for applications running on a TNSERV port.</p></td></tr> | |||
</table> | </table> | ||
</td></tr> | |||
< | <tr><th>outlistid</th> | ||
issued during the login process. These could be error messages during a failed | <td>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: | ||
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: | |||
<ul> | <ul> | ||
<li>In a Janus Web Server $Sir_Login, send the output to the browser or the audit trail, or simply swallow it. | <li>In a <var class="product">[[Janus Web Server]]</var> <var>$Sir_Login</var>, send the output to the browser or the audit trail, or simply swallow it.</li> | ||
<li> | |||
<li>In a <var class="product">[[Janus Sockets]]</var> <var>$Sir_Login</var>, send the output to the audit trail or to one or more open sockets.</li> | |||
</ | |||
<li>In a <var class="product">Janus Web Server</var> or a <var class="product">Janus Sockets</var> <var>$Sir_Login</var>, capture terminal output to a $list via <var>[[$List_Capture]]</var>. | |||
<p> | |||
If <var>$Sir_Login</var> is invoked with an output [[$lists|$list]], the X'06' bits of the <var class="product">Model 204</var> <var>[[MSGCTL parameter|MSGCTL]]</var> user parameter are automatically cleared, then restored upon completion of <var>$Sir_Login</var> processing. This ensures that logon messages are sent to the "terminal" and so the output $list, no matter what the current <var>MSGCTL</var> setting is. APSY subsystems that suppress messages do so by setting one or both of the <var>MSGCTL</var> X'06' bits. <var>$List_Capture</var> does not affect the <var>MSGCTL</var> setting. </p></li> | |||
</ul></td></tr> | |||
</table> | |||
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. | |||
<strong>Note:</strong> It cannot be overemphasized that before <var>$Sir_Login</var> 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. | ==Usage notes and examples== | ||
<p class="note"><strong>Note:</strong> It cannot be overemphasized that before <var>$Sir_Login</var> 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. </p> | |||
===Trusted Login=== | ===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. | 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 <var class="product">Model 204</var> 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. | 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 <var class="product">Model 204</var> 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 <var class="product">Janus Sockets</var> client request. | ||
===Protected Access and External Authorizers=== | ===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 <var class="product">Janus Web Server</var> <var>NEWSESCMD</var> request that illustrates this technique: | |||
The following is a fragment of code from a Janus Web Server NEWSESCMD request that illustrates this technique: | |||
<p class="code"> IF $WEB_CERT_INFO('CNAME', 1) EQ 'Trusted CA' THEN | <p class="code"> IF $WEB_CERT_INFO('CNAME', 1) EQ 'Trusted CA' THEN | ||
Line 91: | Line 123: | ||
</p> | </p> | ||
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): | A <var class="product">Janus Sockets</var> server <var>NEWSESCMD</var> request that accomplishes the same thing is virtually identical (whether using a $function, as below, or using a comparable Socket object method): | ||
<p class="code"> IF $SOCK_CERT_INFO(1, 'CNAME', 1) EQ 'Trusted CA' THEN | <p class="code"> IF $SOCK_CERT_INFO(1, 'CNAME', 1) EQ 'Trusted CA' THEN | ||
Line 105: | Line 137: | ||
<ul> | <ul> | ||
<li>A trusted certifying authority certificate with a common name of | <li>A trusted certifying authority certificate with a common name of "Trusted CA" must be added to the appropriate port with the [[JANUS ADDCA]] command. | ||
<li>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. | <li>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. | ||
</ul> | </ul> | ||
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 | 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: | ||
<p class="code"> IF $WEB_CERT_INFO('CNAME', 1) EQ 'Trusted CA' THEN | <p class="code"> IF $WEB_CERT_INFO('CNAME', 1) EQ 'Trusted CA' THEN | ||
Line 124: | Line 156: | ||
</p> | </p> | ||
An even more sophisticated NEWSESCMD application could itself maintain the USERS file that contains | An even more sophisticated <var>NEWSESCMD</var> application could itself maintain the USERS file that contains, for example, a common name, MD5 certificate hash and a <var class="product">Model 204</var> user ID associated with the certificate. When a certificate is received, the common name and MD5 hash can be looked up in the database: | ||
<p class="code"> %CNAME = $WEB_CERT_INFO('CNAME') | <p class="code"> %CNAME = $WEB_CERT_INFO('CNAME') | ||
Line 141: | Line 173: | ||
</p> | </p> | ||
If the received certificate is not in the database, the | 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: | ||
<p class="code"> %USERID = $WEB_USER | <p class="code"> %USERID = $WEB_USER | ||
%PASSWORD = $WEB_PASSWORD | %PASSWORD = $WEB_PASSWORD | ||
IF %USERID NE | IF %USERID NE '' AND %PASSWORD NE '' THEN | ||
%RC = $Sir_Login(%USERID, %PASSWORD) | %RC = $Sir_Login(%USERID, %PASSWORD) | ||
IF NOT %RC THEN | IF NOT %RC THEN | ||
Line 156: | Line 188: | ||
</p> | </p> | ||
[[$Web_Password]], like $Sir_Login, causes request cancellation if used outside of NEWSESCMD processing. | <var>[[$Web_Password]]</var>, like <var>$Sir_Login</var>, causes request cancellation if used outside of <var>NEWSESCMD</var> processing. | ||
Finally, a successful login for a specific | 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: | ||
<p class="code"> | <p class="code">SUCCESS: | ||
IN FILE USERS STORE RECORD | |||
CNAME = %CNAME | |||
MD5HASH = %MD5HASH | |||
USERID = %USERID | |||
END STORE | |||
STOP | |||
</p> | </p> | ||
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. | 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 <var>[[JANUS ADDCA]]</var> command. | ||
A similar technique can be used with Janus Sockets, though, of course, when a certificate is not in the database, the | A similar technique can be used with <var class="product">Janus Sockets</var>, 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 <var>$Web_User</var> and <var>$Web_Pass</var>. The appropriate technique would largely depend on the protocol being used over TCP/IP. | ||
===Telnet Example=== | ===Telnet Example=== | ||
The following illustrates how a user ID and password can be obtained from a user when using the telnet protocol over a <var class="product">Janus Sockets</var> connection: | |||
The following illustrates how a | |||
<p class="code"> REPEAT FOREVER | <p class="code"> REPEAT FOREVER | ||
Line 181: | Line 212: | ||
%RC = $SOCK_RECVPRS(1, %DATA, 9999999) | %RC = $SOCK_RECVPRS(1, %DATA, 9999999) | ||
%USERID = $UPCASE(%DATA) | %USERID = $UPCASE(%DATA) | ||
IF %USERID NE | IF %USERID NE '' THEN | ||
%RC = $SOCK_SEND(1, 'Password: ') | %RC = $SOCK_SEND(1, 'Password: ') | ||
%RC = $SOCK_RECVPRS(1, %DATA, 9999999) | %RC = $SOCK_RECVPRS(1, %DATA, 9999999) | ||
%PASSWORD = $UPCASE(%DATA) | %PASSWORD = $UPCASE(%DATA) | ||
END IF | END IF | ||
IF %PASSWORD NE | IF %PASSWORD NE '' THEN | ||
%LIST = $LISTNEW | %LIST = $LISTNEW | ||
%LOGIN = $Sir_Login(%USERID, ,%PASSWORD, , ,%LIST) | %LOGIN = $Sir_Login(%USERID, ,%PASSWORD, , ,%LIST) | ||
Line 200: | Line 231: | ||
</p> | </p> | ||
Again, this kind of approach can be combined with a certificate-based approach where, if a received certificate is in the database, no | 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=== | ===Proxy Servers=== | ||
Another use of <var>$Sir_Login</var> 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 <var class="product">Janus Web Server</var> receives a request from a specific IP address, it can be certain of these: | |||
Another use of <var>$Sir_Login</var> 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: | |||
<ul> | <ul> | ||
Line 211: | Line 241: | ||
</ul> | </ul> | ||
Finally, the proxy server in question is known to place the validated | 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: | ||
<p class="code"> IF $WEB_IPADDR EQ %PROXY_IPADDR THEN | <p class="code"> IF $WEB_IPADDR EQ %PROXY_IPADDR THEN | ||
%USERID = $UPCASE($WEB_HDR_PARM('USERID')) | %USERID = $UPCASE($WEB_HDR_PARM('USERID')) | ||
IF %USERID NE | IF %USERID NE '' THEN | ||
%RC = $Sir_Login(%USERID) | %RC = $Sir_Login(%USERID) | ||
IF NOT %RC THEN | IF NOT %RC THEN | ||
Line 223: | Line 253: | ||
</p> | </p> | ||
In this example, the <var>$Sir_Login</var> will still fail if the | In this example, the <var>$Sir_Login</var> 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 <var>$Sir_Login</var>: | ||
<p class="code"> IF $WEB_IPADDR EQ %PROXY_IPADDR THEN | <p class="code"> IF $WEB_IPADDR EQ %PROXY_IPADDR THEN | ||
%USERID = $UPCASE($WEB_HDR_PARM('USERID')) | %USERID = $UPCASE($WEB_HDR_PARM('USERID')) | ||
IF %USERID NE | IF %USERID NE '' THEN | ||
%RC = $Sir_Login(%USERID, , , , 'GUEST') | %RC = $Sir_Login(%USERID, , , , 'GUEST') | ||
IF NOT %RC THEN | IF NOT %RC THEN | ||
Line 235: | Line 265: | ||
</p> | </p> | ||
In this case, the user will pick up default user privileges for the Online but will run under the | 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 | 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: | ||
<p class="code"> IF $WEB_IPADDR EQ %PROXY_IPADDR THEN | <p class="code"> IF $WEB_IPADDR EQ %PROXY_IPADDR THEN | ||
Line 249: | Line 279: | ||
</p> | </p> | ||
The combination of <var>$Sir_Login</var> 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 | The combination of <var>$Sir_Login</var> and <var>NEWSESCMD</var> processing provides a very flexible set of facilities that allows a site to tailor <var class="product">Janus Web Server</var> and <var class="product">Janus Sockets</var> 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 <var>NEWSESCMD</var> code be examined by as many eyes as is reasonable, and that Rocket Software be contacted to review <var>NEWSESCMD</var> code. | ||
==Sample APSY== | ==Sample APSY== | ||
A sample | A sample APSY subsystem that can be used with the <var>NEWSESCMD</var> subcommand is provided by Rocket Software (it is the same sample subsystem provided for use with the <var>[[VTLAPSY parameter|VTLAPSY]]</var> parameter for IODEV7 users). The code is in the SIRIUS file, beginning with <var class="product">[[ULSPF|UL/SPF]]</var> 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. | ||
[[Category:Janus Web Server $functions|$Sir_Login]] | [[Category:Janus Web Server $functions|$Sir_Login]] | ||
[[Category:$Functions|$Sir_Login]] | [[Category:$Functions|$Sir_Login]] | ||
[[Category:Janus Web Server|$Sir_Login]] | |||
[[Category:Janus Sockets|$Sir_Login]] |
Latest revision as of 06:14, 30 May 2018
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:
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. | ||||||
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.
| ||||||
options | A blank-delimited set of option words. These options can be:
| ||||||
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:
|
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.