ahulikavi
24th February 2005, 07:51
Hi,

Have developed a 3gl solution for password ageing and controlling no of logins.

Purpose :
1. Enforce Password change after policy number of days (30 in our case)
2. Restrict multiple logins as per policy
3. Quickly list out logged in users in client instead of using licmon etc

Method :
1. create 2 tables one for password policy and max logins allowed per user and another to store current logins
2. create 3 gl session and add it in BMS as startup boot session.
3. Session check user status as per password policy and max logins allowed and takes neccessary action i.e. allow/dissallow login, force password change.

We use it on IVc4 with BW / Worktop on Sun Solaris 2.6. You may need to change certain OS specific commands for this to work at your end.


Now for the code ...Hope this helps, let me know any suggestions for improvement


||******************************************************************************
|* tdtcdmsg : VRC B40C Live
|* Title : Login and Password Control
|* Author : Akshay Hulikavi
|* Date : 2004-02-09 [09:17]
|******************************************************************************
|* License :
|* Copyright 2004 by Akshay Hulikavi
|*
|* All Rights Reserved
|*
|* Permission to use, copy, modify, and distribute this software and its
|* documentation for any purpose and without fee is hereby granted,
|* provided that the above copyright notice appear in all copies and that
|* both that copyright notice and this permission notice appear in
|* supporting documentation.
|*
|* Akshay Hulikavi DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|* AND FITNESS, IN NO EVENT SHALL Vamsi Potluru BE LIABLE FOR ANY
|* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
|* OR PERFORMANCE OF THIS SOFTWARE.
|******************************************************************************

table ttdtcd991 | User login info
table ttdtcd990 | Current logins

string date.str(10), bucket(50), progname(512)
long procid, proclist(100), i, j, user.bshell.pid, ret, no.of.logins
long info(PSMAXSIZE)


function main()
{
if logname$ <> "root" or logname$ <> "smis1" then | Not for super user
user.bshell.pid = bshell.pid()
remove.user.from.990.if.disconnected()

db.retry.point()
no.of.logins = 0

select tdtcd991.*
from tdtcd991 for update
where tdtcd991._compnr = 010 | Only applicable for live company
and user = :logname$
selectdo
select count(tdtcd990.user):no.of.logins
from tdtcd990
where tdtcd990.user = :logname$
selectdo
endselect
if no.of.logins >= tdtcd991.maxl then | logins exceed maximum allowed for user ?
kill.and.exit()
exit(0)
else
tdtcd990.pid = user.bshell.pid
tdtcd990.user = logname$
tdtcd990.serv = hostname$()
tdtcd990.date = sprintf$("%D(%02d/%02m/%04Y)", date.num())
tdtcd990.comp = get.compnr()
db.insert(ttdtcd990, db.retry)
endif

date.str = sprintf$("%D(%02d/%02m/%04Y)", tdtcd991.lldt)

| tdtcd991.npwc = tdtcd991.lpwc + 30 | Add next pwc date
message( "Welcome "&logname$&", This is your login no "&str$(no.of.logins + 1)&" you are allowed max "&str$(tdtcd991.maxl)&" logins")

if date.num() >= tdtcd991.npwc then |time to Change password
ret = shell( "passwd",SHELL_CONFIRM)
if ret = 0 then |Password successfully changed
tdtcd991.lpwc = date.num() |Capture password change date
tdtcd991.npwc = tdtcd991.lpwc + 30 |Next change on
endif
endif
tdtcd991.lldt = date.num() | Last Login date
tdtcd991.lltm = time.num() | Last login Time
tdtcd991.nolg = tdtcd991.nolg + 1 | Number of logins till date
db.update(ttdtcd991, db.retry)
selectempty
message( "Welcome "&logname$&", This is your login no "&str$(no.of.logins + 1)&" you are allowed max "&str$(tdtcd991.maxl)&" logins")
tdtcd991.user = logname$
tdtcd991.lpwc = date.num() | Assume today as lastpw change if first time login
tdtcd991.npwc = tdtcd991.lpwc + 30 | Add next pwc date
tdtcd991.lldt = date.num() | Last Login Date
tdtcd991.lltm = time.num() | Last Login Time
tdtcd991.nolg = tdtcd991.nolg + 1 | no of logins till date
tdtcd991.maxl = 1 | Default Only 1 login allowed
db.insert(ttdtcd991, db.retry)
endselect
commit.transaction()



bms.add.mask("bms.shutdown") | to detect the shutdown event which is sent by the system
while true
bucket = bms.receive$()
if bucket = "bms.shutdown" then
remove.user.from.990()
exit(0)
endif
endwhile

endif
}

function remove.user.from.990()
{
select tdtcd990.*
from tdtcd990 for update
where tdtcd990.user = :logname$
and tdtcd990.pid = :user.bshell.pid
selectdo
db.delete(ttdtcd990, db.retry)
endselect
commit.transaction()
}

function kill.and.exit()
{
i = 1
procid = -1
procid = pstat(procid, progname, info )

while procid > 0
proclist(i) = procid
i = i + 1
procid = pstat( procid, progname, info )
endwhile

for j = i to 1 step -1
if proclist(j) <> pid then | Keep current process active so that we can remove everything and then
kill(proclist(j)) | display message
endif
endfor

message( " *** LOGIN DISSALLOWED : "&logname$&", you have already logged in "&str$(no.of.logins)&" times, you are allowed max "&str$(tdtcd991.maxl)&" logins")
kill(pid)
}

function remove.user.from.990.if.disconnected()
{
select tdtcd990.*
from tdtcd990 for update
where tdtcd990.user = :logname$
selectdo
ret = shell( "ps -p "&str$(tdtcd990.pid),SHELL_NO_OUTPUT) | Check if process active at OS level
if ret <> 0 then | Process does not exist at OS Level, probably killed or disconnected
db.delete(ttdtcd990, db.retry) | Delete from ligins table if bshell pid not found
endif
endselect
commit.transaction()
}




Note : When you need a situation when no one should log into baan just change tdtcd991.maxl field to 0 for all users except yourself ;-), this will not allow anybody else to login.

manojsharma
24th February 2005, 08:36
seems good. Please paste the structure of tables also

NPRao
24th February 2005, 20:22
Akshay,

There is a small bug in the program -

ret = shell( "passwd",SHELL_CONFIRM)
if ret = 0 then |Password successfully changed
tdtcd991.lpwc = date.num() |Capture password change date
tdtcd991.npwc = tdtcd991.lpwc + 30 |Next change on
endif

The shell() takes me to change password and I press Control-C to abort/cancel the password change process and I get a return value of 0 and the table is updated that I have changed the password.
I think Dave's program looks at the Unix System's Last Password change info.

ahulikavi
25th February 2005, 11:57
Thanks Prashant,

Point taken, incidently we have also set pw policy at OS, so if user does not change passwords, then login is dissallowed by OS itself.

Another point is setting of resource variable ds_timeout_detect, if this is not set then bshell process stays active at OS in case of connection loss, say due to lan/wan link failure.

In such case till the bshell process is terminated - determined by ds_timeout_detect ( default 30 mins) above 3GL will find user already logged in and not allow further logins.

In our case we have set ds_timeout_detect to 1 minute to handle this.

veyant
6th August 2005, 13:52
Hi,

As per you

create 3 gl session and add it in BMS as startup boot session.

what do you mean by BMS startup boot session. are you refering to bms_mask file in $BSE/lib.

what entry whould be made to fulfill the requested activity of adding it in BMS startup Boot.

thanks
Sandeep

manojsharma
8th August 2005, 08:08
Hi Sandeep,

BMS marks are used while sending bucket messages. If a process sends a bucket message (to all processes within the same bshell) with the given mask and no processes have this mask on. the specified session or object will be started.

Use session no.ttadv4188m000 (Main BMS Mask Data).


To activate the changes, use the "continue" option to convert the data to runtime. The information will be stored in the file "$BSE/lib/bms_mask".

ganesh_kapase
29th October 2005, 01:45
Hi Manoj

You mean to say by adding the above session developed by Mr.Akshay in the ttadv4188m000 it will start working immediately all the functions used in the session.

If I am wrong please correct me.


Ganesh

manojsharma
29th October 2005, 09:17
Yes Ganesh, The program will activate automatically when a user logged in.

k_d_mahajan
12th March 2008, 06:47
Hello Akshay,
Its really a nice 3GL you have developed.
Can you give me details of Table definations
1) ttdtcd991 | User login info &
2) ttdtcd990 | Current logins

baan_tools_IV
3rd April 2008, 14:48
Hello Akshay,

can please post the table structure:
1) ttdtcd991 | User login info &
2) ttdtcd990 | Current logins


Baan_tools_IV
sandara@rediffmail.com

simplerosy
24th June 2008, 09:52
Hi,
Can you send me updated script and Table Definations please.
-Rosy

jbaanm
17th July 2008, 00:39
My script failing with some error
If I debug, its getting stuck at
bms.add.mask("bms.shutdown") | to detect the shutdown event which is sent by the system
while true
bucket = bms.receive$()
if bucket = "bms.shutdown" then
remove.user.from.990()
exit(0)
endif
endwhile


Is there any other way you can run a session like this immediately after login

jbaanm
6th January 2009, 02:57
The following script part is running in the background till the user is logged out. That is taking lots of CPU time and slowing the down the server.
Whats the alternative to this? This part is need only to delete a entry after logout.

bms.add.mask("bms.shutdown") | to detect the shutdown event which is sent by the system
while true
bucket = bms.receive$()
if bucket = "bms.shutdown" then
remove.user.from.990()
exit(0)
endif
endwhile