Novell is now a part of Micro Focus

How to Clear a User's Connection Using a Perl Script

Articles and Tips: article

Michael Lee
Directory Engineer
Phoenix Home Life
Michael_Lee@phl.com

01 Jun 2001


This article discusses how to clear a user's NDS eDirectory connection using a Perl script.

Introduction

This AppNote describes a method to clear a user's NDS eDirectory connection. There are times when a user's network connection needs to be cleared. At the Phoenix Home Life Insurance Company, we restrict the number of concurrent connections that a typical user has. This user restriction is encouraged for security reasons.

For example, in the AppNote entitled "NetWare Security: Closing the Doors to Hackers" in the June 2000 issue (http://support.novell.com/techcenter/articles/ana20000603.html), it recommends: "Set up connection limits for users. One connection is sufficient for everyone other than Admin. (If you are using ZENworks, you will need two connections per user)." This setting can be modified for a user via the NWAdmin or ConsoleOne utilities. When changing the properties of a user, go to the Login Restrictions screen. Figure 1 shows this screen in ConsoleOne.

Login Restrictions screen in ConsoleOne.

When a user attempts to log in to Novell Directory Services (NDS) eDirectory, NDS checks the number of user connections currently being consumed for that user. It will not allow the user to log in if the number of that user's connections is at its limit. When a user gracefully logs out of NDS, such as restarting or shutting down Windows, the number of connections for that user will be decreased, thereby allowing the user to log into NDS again. If a NetWare server has a user connection and has not received a packet from the user's PC within a certain time frame (this is configurable), a watchdog packet is sent to the PC. After an amount of time passes without a response (also configurable), a second packet is sent. After a number of watchdog packets have been sent without a response (again configurable), the server will finally clear the user's connection. Unfortunately, this may take several minutes.

I think many of us have experienced the lock-up of a PC on which we are working. When a user does not actually shutdown his or her PC, NDS will continue to think that the user is still logged in until the full watchdog process has completed. What happens if the maximum number of NDS connections had been reached on the last login? NDS will not allow this user to log back in until it actually clears the user's connection. The user will have to continually attempt to log into NDS until NDS finally clears his connection and allows him to log back in. This can be frustrating for a user, as well as for a support person. This AppNote describes a process to solve this problem.

Need for the Script

At my company we have three levels of desktop support. Level 1 support staff are our "foot soldiers." All support requests go to them first. They document and research the problem and solve a great number of problems daily. If a solution can not be obtained quickly or needs to be researched in depth, the problem is elevated to Level 2 support. Level 2 support staff have additional NDS rights that are not granted to Level 1 support staff. Those few extensive problems that are not solved by the Level 2 support are finally elevated to the Level 3 on-call support person. Level 3 staff also have many other tasks, such as evaluating and upgrading server hardware and operating systems.

Some time ago, a couple of Level 2 support staff people spoke to me about the problem described earlier-where a user's PC would "hang" and the user could not log into NDS after rebooting because the user is still considered to be logged in. This actually happens quite often and they asked me to develop a solution.

In researching a solution for this problem, I found that for each user's connection to NDS, the network address for that connection is stored within the user's network address attribute. For instance, if a user is logged into NDS eDirectory on two PCs, you will see two network addresses when looking at the user's Network address within the NWAdmin or ConsoleOne utility. An example of a ConsoleOne environment screen displaying the network address is shown in Figure 2.

ConsoleOne screen displays the network address.

It seemed that NDS might use this attribute to determine the number of NDS connections a user is currently using. Unfortunately, I could not find a way to use NWAdmin or ConsoleOne to remove an entry from this attribute to test my theory. Even if there was a way to remove an entry from this attribute using one of these utilities, our Level 1 support staff would not be not able to solve this problem because (1) they do not have permission to update User objects, and (2) they are not very familiar with these utilities.

Goals of the Solution

Before designing a solution, I determined my goals:

  1. Remove an entry from the network address attribute.

  2. Allow a Level 1 support staff to clear this connection without granting additional rights.

  3. Make the solution accessible to the Level 1 support staff at any time of day.

  4. And, of course, make the solution easy to use.

Initially, I needed to determine whether there was a way to remove entries from the Network Address attribute and whether removing entries to this attribute would reduce the number of NDS connections for a user. I decided to create a test program to see if this could be done. Because of my familiarity with the Perl programming language, I decided to write my test program or script in Perl. Perl runs on NetWare servers and on PCs and is very good at parsing and manipulating data. I was already familiar with manipulating NDS objects using the NDSm Perl modules by Steinar Kleven. You can find more information about the modules at the site: http://www.ahs.hist.no/distr/NDSm.

My test plan was as follows:

  1. At a PC, log in to NDS using a test user.

  2. Use NWAdmin to be sure the Network Address attribute has a value for the test user.

  3. Create and run a test Perl script that will log into the NDS tree as a user that has rights to modify the test user and clear the Network Address attribute for that user.

Design and Solution

The test Perl script worked exactly as I hoped: it removed the entry from the Network Address attribute for the test user's object. Next, I asked the Level 2 staff to call me when they were notified that a user's PC had locked, was rebooted, and the user was unable to log in because no available connections were available. When that occurred, I quickly changed my test Perl script to remove the Network Address entries from the user experiencing the problem. We then asked the user to re-attempt the log in and he succeeded. The experiment worked!

The solution for goal 1 was achieved. To address the rest of the goals, I added some things to the initial test Perl script. The final Perl script runs on a NetWare server so that it can run continuously and allow many to use the script. The script launches during the boot-up of the server because the commands to run the script are stored in the server's AUTOEXEC.NCF file. When logging in to NDS, each Level 1, 2, and 3 support staff receives drive mappings to this server.

The first step in the Perl script is to log into the NDS tree. The user ID and password used to login are stored in an encrypted format so they would be difficult to obtain from the script. High in the NDS tree, the rights to change the attribute values of a user are granted and the rights are allowed to flow down to every user object. Rights to the Perl script are also restricted, so only a few of the Level 3 staff have access to read or update the script.

Every twenty seconds, the script checks for the existence of a CLEARCON (clear connections) input file. This file becomes the input to the script. It tells the script which users' Network Address attributes to clear. If the CLEARCON input file is found, the script opens and reads the file. It does some minor manipulation such as adding our NDS tree's Organization to the end of the line read if it is not found. The script removes the Network Address attribute values for the object, checking the return code for success or not. The log file is updated. When all entries in the input file have been cleared, the file is deleted.

A CLEARCON DOS batch file is used by the Level 1 support staff to create the CLEARCON input file. Level 1 support staff have rights to write to this input file. The name of the user object to be cleared is passed as an argument to the DOS batch file, and the DOS batch file adds the name to the end of the CLEARCON input file.

This solution solves all of my goals previously mentioned:

  1. The Perl script running on the server removes the Network Address attribute entries from all entries found in the CLEARCON input file.

  2. The Level 1 support staff have write rights to the CLEARCON input file. The CLEARCON DOS batch file is located in the PUBLIC directory of their home server so all can execute the batch file. The rights to update the actual user objects are granted within the Perl script so Level 1 support staff do not need to be granted the rights to update user objects.

  3. The Perl script starts when the server is booted and stays running continuously so users' connections can be cleared at any time.

  4. The Level 1 support staff type in a single command to clear a user's connection. For example, to clear a user jones located in the finance.hartford.phoenix container, a Level 1 support staff simply runs the command: clearcon jones.finance.hartford.

Logic Pieces

The CLEARCON DOS batch file (clearcon.bat) is only three lines, as shown below. It sends the argument passed to the end of the CLEARCON input file (o:\clearcon\toclear) and echoes a message back to the support person.

@echo off
echo %1 >>o:\clearcon\toclear
echo Scheduling %1 to be cleared.

The final CLEARCON Perl script is shown below. I removed the code that decrypts the user ID and password. In this AppNote I want to focus on the connection clearing rather than the decryption method. These explanatory notes correspond to the numbered lines in the sample script.

(1) Set the directory to check for the CLEARCON input file.

(2) Set the filename of the CLEARCON input file.

(3) Set the filename of the renamed CLEARCON input file.

(4) Set the filename of the log file.

(5) Set the number of seconds to sleep before looking for the CLEARCON input file.

(6)Set the login id's user name.

(7) Set the login id's password.

(8) Call the DSSetup subroutine to log into NDS.

(9) Display an information message on the CLEARCON Perl script's NetWare server screen.

(10) Set an infinity variable to one.

(11) Do loop (to continuously execute lines 12 - 15).

(12) Attempt the rename of the CLEARCON input file to the CLEARCON temporary file. The return code of this rename is set. The purpose of this rename is for the script to use a temporary file as input in case a support person attempts to add to the CLEARCON input file while the script is running. If that occurred, the CLEARCON Perl script could miss an attempt to clear a connection.

(13) If the rename was successful (the CLEARCON input file existed), call the workOnFile subroutine to work on this file.

(14) Sleep or wait the number of seconds set in line 5.

(15) Increment the infinity variable (this line is commented out so it will not execute). I used this line in my testing phase so the do loop will end after ten loops (set in line 16).

(16) The end of the do loop. Since line 15 is commented, the loop, and so the Perl script, will run continuously.

(17) Free the allocated memory buffers before ending program.

(18) Declare subroutine workOnFile.

(19) Open the CLEARCON temporary file to be read (remember that this is really the CLEARCON input file renamed to the temporary filename).

(20) Continue reading the temporary file to the file's end removing end of line character from the set variable.

(21) Check for the organization phoenix at the end of the line. If it is not found, then add a period and the organization phoenix at the end. One could easily add other abbreviations here also.

(22) Remove a period at the beginning of the line if found.

(23) Modify the particular object designated and set the return code.

(24) A tricky line that sets the beginning of the logging variable depending on the return code from the modify in line 23.

(25) Call the prLog subroutine to print to the log file.

(26) Close the CLEARCON temporary file.

(27) Delete the CLEARCON temporary file.

(28) Declare subroutine DSSetup.

(29) Tell the Perl script to use the NDSm modules.

(30) Declare a new NDSm context instance.

(31) Tell the Perl script to use the NDSm buffer modules.

(32) Declare a new NDSm buffer instance.

(33) Log in to the NDS tree, setting the return code and checking the return code for an error.

(34) Could not log in, so wait or sleep two seconds.

(35) Try to log in to NDS again, setting the return code and checking the return code for an error.

(36) Exit program displaying error if login is still unsuccessful.

(37) Initialize a buffer to modify an NDS object.

(38) Set the buffer to remove the NETWORK ADDRESS attribute.

(39) Declare subroutine prLog.

(40) Set the log message.

(41) Open to append to the end of the log file.

(42) Set the current date and time.

(43) Print the log message and the current date and time.

(44) Close the log file.

Sample Script

A line of communication between the different levels of support allowed us to create a solution that actually benefits the network users, who are our real "clients."

# This is a program to clear an id's connections from NDS by Michael Lee
$dirCheck = "data:clearcon/"; # (1)
$fileName = "toclear"; # (2)
$temName = "working"; # (3)
$logName = "logout.log"; # (4)
$sleep = 20; # (5)
$loginId = ".clearid.phoenix"; # (6)
$passwordId = "password"; # (7)
&DSSetup; # (8)
print "Support script to clear connections from NDS."; # (9)
$infinit = 1; # (10)
do { # (11)
   $success = rename "$dirCheck$fileName", "$dirCheck$temName"; # (12)
   &workOnFile if $success; # (13)
   sleep $sleep; # (14)
#   $infinit++; # (15)
} until ($infinit > 10); # (16)
$netAddRemove->FreeBuf (); # (17)
sub workOnFile { # (18)
   open FIL, "$dirCheck$temName"; # (19)
   while (chomp ($_ = <FIL>)) { # (20)
      s/([^pP][^hH][^oO][^eE][^nN][^iI][^xX]$)/$1.phoenix/; # (21)
      s/^\.//; # (22)
      $ret = $netAddRemove -> ModifyObject ("", $_, 0, 0); # (23)
      $retStr = ($ret == -1 ? "Successfully" : "Unsuccessfully"); # (24)
      prLog ("$retStr removed network addresses from $_"); # (25)
   }
   close FIL; # (26)
   unlink "$dirCheck$temName"; # (27)
}
sub DSSetup { # (28)
   use NDSm::NDSContext; # (29)
   $C = new NDSm::NDSContext; # (30)
   use NDSm::Buf_T; # (31)
   $netAddRemove = new NDSm::Buf_T; # (32)
   if (($loginRet = $C -> Login (0, $loginId, $passwordId, 0)) != 0) { # (33)
      sleep (2); # (34)
      if (($loginRet = $C -> Login (0, $loginId, $passwordId, 0)) != 0)
	  { # (35)
         die ("Error logging into DS, returned $loginRet\n"); # (36)
      }
   }
   $netAddRemove -> InitBuf ("", "DSV_MODIFY_ENTRY"); # (37)
   $netAddRemove -> PutChange ("", "DS_REMOVE_ATTRIBUTE", "NETWORK ADDRESS");
   # (38)
}
sub prLog { # (39)
   my $logMess = shift; # (40)
   open LOG, ">>$dirCheck$logName"; # (41)
   $logTime = localtime (); # (42)
   print LOG "$logMess at $logTime\n"; # (43)
   close LOG; # (44)
}

Conclusion

The next time a user does not actually shut down his or her PC and NDS continues to think the user is logged in, you can clear their connection using a Perl script such as the one presented in this AppNote.

* Originally published in Novell AppNotes


Disclaimer

The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.

© Copyright Micro Focus or one of its affiliates