**DONOTDELETE**
(Lurker)
2002-06-05 02:49 PM
LogonHours user properties

I have a small problem - I need to query the Logon Hours for all users in the domain and reset those ones that have been changed (and generate a security warning).

Unfortunately, I am NT4 only so do not have access to the domain via LDAP. I therefore need to use the WinNT provider. I am using NT4 Workstation with the ADSI client installed. I can enumerate the users OK, but am having trouble getting the LogonHours property. Is it LogonHours? Is there a way to enumerate all of the properties that are available for any given object?

At the moment the Security team are using User Manager to group select all users in the domain and setting the logon hours to what they should be. This send the domain controllers (and network links) into a tailspin as they try to replicate 9000+ user accounts!! Anything wuold be better than this - any suggestions?

Thanks,
Michael.


Les
(KiX Master)
2002-06-05 02:59 PM
Re: LogonHours user properties

The ADSI SDK has with it a help file that lists all the properties and methods. It can be downloaded from M$. A search on this board should reveal the URL.

ShawnAdministrator
(KiX Supporter)
2002-06-05 03:19 PM
Re: LogonHours user properties

plus, loginhours is one of those "freak'n" byte arrays, like the SID property - Kixtart can't really interpret it too well (actually, not all all - to the best of my knowledge) [Frown]

-Shawn


Howard Bullock
(KiX Supporter)
2002-06-05 03:23 PM
Re: LogonHours user properties

I can provide a compiled Perl Solution later today if I know what it is you actually want to do.

[ 05 June 2002, 16:29: Message edited by: Howard Bullock ]


**DONOTDELETE**
(Lurker)
2002-06-05 03:25 PM
Re: LogonHours user properties

I figured that it must be a byte array - should be 21 bytes I think. Is there a way to at least set this property using kix so that I can script it for outside hours?

ShawnAdministrator
(KiX Supporter)
2002-06-05 03:40 PM
Re: LogonHours user properties

I just tried this:

$user.loginhours = 255,255,255,255,255

and also tried dimming a var and populating it seperately, get the following error:

COM exception error "loginhours" (Active Directory - The directory datatype can
ot be converted to/from a native DS datatype
) [1/1]

which kinda makes sense i guess - WinNT is expecting an array of bytes - and the best we can do is pass an array of longs (five longs = 20 bytes?). Wonder if one could pass an array of CHR()'s ?

-Shawn

p.s. Tried a 21 element array of CHR()'s and also tried maxing out the longs, eg:

$user.loginhours = 4294967295,4294967295,4294967295,4294967295,4294967295

[Frown]

[ 05 June 2002, 15:49: Message edited by: Shawn ]


**DONOTDELETE**
(Lurker)
2002-06-05 07:00 PM
Re: LogonHours user properties

OK, I have come up with the following code. It rather inelegant and VERY slow, but it does work. It took nearly an hour to run against our domain. It does have the advantage of not modifying every single user account and therefore does not trigger full domain synchronisation.

code:
BREAK ON

$DefaultLevel=2

DIM $ValidTimes[3]
DIM $TimeString[3]

$ValidTimes[0]='All'
$ValidTimes[1]='Sunday 7:00 AM - 10:00 PM,Monday 7:00 AM - 10:00 PM,Tuesday 7:00 AM - 10:00 PM,Wednesday 7:00 AM - 10:00 PM,Thursday 7:00 AM - 10:00 PM,Friday 7:00 AM - 10:00 PM,Saturday 7:00 AM - 10:00 PM'
$ValidTimes[2]='Sunday 7:00 AM - 8:00 PM,Monday 7:00 AM - 8:00 PM,Tuesday 7:00 AM - 8:00 PM,Wednesday 7:00 AM - 8:00 PM,Thursday 7:00 AM - 8:00 PM,Friday 7:00 AM - 8:00 PM,Saturday 7:00 AM - 8:00 PM'

$TimeString[0]='All'
$TimeString[1]='Sunday-Saturday,07:00-22:00'
$TimeString[2]='Sunday-Saturday,07:00-20:00'

CLS

AT(0,40) 'Process started at @TIME' ?

$Incorrect=0

$Domain=GETOBJECT('WinNT://RBSI')
IF @ERROR=0
$Domain.Filter='User',''
FOR EACH $User IN $Domain
$Counter=$Counter+1
AT(1,40) 'Processed $Counter users'
$Level=$DefaultLevel
$Exclude=0
FOR EACH $Group IN $User.Groups
SELECT
CASE $Group.Name='Domain Admins'
$Exclude=1
CASE $Group.Name='Exclusion Hours'
$Level=0
CASE $Group.Name='Gibraltar Users' OR $Group.Name='LH Users'
IF $Level>1
$Level=1
ENDIF
ENDSELECT
NEXT
IF $Exclude=0
SHELL 'CMD /C NET USER "'+$User.Name+'" /DOMAIN>%Temp%\UserDetails.TXT'
$Hours=''
$Collect=0
IF OPEN(1,'%Temp%\UserDetails.TXT',2)=0
$Line=READLINE(1)
DO
IF SUBSTR($Line,1,LEN('Local Group Memberships'))='Local Group Memberships'
$Collect=0
ELSE
IF SUBSTR($Line,1,LEN('Logon hours allowed'))='Logon hours allowed'
$Collect=1
ENDIF
ENDIF
IF $Collect AND LEN($Line)>0
IF $Hours<>''
$Hours=$Hours+','
ENDIF
$Hours=$Hours+LTRIM(SUBSTR($Line,20,LEN($Line)))
ENDIF
$Line=READLINE(1)
UNTIL @ERROR<>0
IF $Hours<>$ValidTimes[$Level]
$Incorrect=$Incorrect+1
AT($Incorrect-1,0)
COLOR r+/n
$User.Name ' hours not correct' ?
COLOR n/n
AT(2,40) 'Found $Incorrect user'
IF $Incorrect>1
's'
ENDIF
SHELL 'CMD /C NET USER "'+$User.Name+'" /TIMES:"'+$TimeString[$Level]+'" /DOMAIN>NUL'
ENDIF
$Result=CLOSE(1)
ENDIF
DEL '%Temp%\UserDetails.TXT'
ENDIF
NEXT
ELSE
'Error @Error while opening object:' ?
' @SError' ?
ENDIF

AT(3,40) 'Process completed at @TIME' ?

Sorry for the lack of comments. If anyone is wanting this I can go back and add them [Wink]


Howard Bullock
(KiX Supporter)
2002-06-05 08:25 PM
Re: LogonHours user properties

comjf, This property can be accessed and written directly in Perl. It can be expanded into 168 characters of 1's and 0's that signify on and off for each hour of the week. This result can be checked, altered, and then written back to the account if necessary. This approach would be much faster than parsing through text output on 'NET USER'.

If you tire of solution or would like to explore this avenue further, just let me know.


**DONOTDELETE**
(Lurker)
2002-06-07 12:07 AM
Re: LogonHours user properties

Hi Howard,

I know I COULD run a Perl script to do it much faster but I don't have any Perl skills and it would be much harder for me to customise later. At this stage I think that it would be better to stick with the slow solution and schedule it to run overnight.

Thanks very much for the offer though.

Perhaps Ruud will come up with a solution to the problem of reading/writing of byte arrays using Kix... I have come across it a couple of times now (also had problems reading SIDs directly).

Thanks to everyone for the help.

Michael.


**DONOTDELETE**
(Lurker)
2002-06-07 05:31 PM
Re: LogonHours user properties

I am not sure what I was doing the other day, but I just ran Howards script to enumerate all properties and added a line to display the value of each. For LoginHours a line of 21 bytes was displayed, which is the correct setting for this property, eg 24x7 is represented as:

ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

This can be converted to a bit stream using the ASC() function.

I don't seem to be able to set the property in this manner, but I can read it OK.

This has reduced my original script execution time from nearly 2 hours to 6 minutes! [Smile]


Howard Bullock
(KiX Supporter)
2002-06-07 07:59 PM
Re: LogonHours user properties

Check your email. I have mailed you the Perl code that should be very close to what you want.

[ 07 June 2002, 19:59: Message edited by: Howard Bullock ]