O Active Directory possuí vários atributos de contas de usuário, entre eles a “janela” de horários permitidos de logon dessas contas, evitando uma conta entrar em computadores e um determinado horário. Porém caso a conta já esteja no computador antes da restrição, não impede que o usuário em questão continue trabalhando.

Aqui iremos sugerir uma forma de, quando houver uma restrição de horário de logon no Active Directory o usuário seja avisado ao usuário antes de chegar o horário e, ao chegar o horário de restrição, a sessão de um usuário seja bloqueada no desktop. Para isso, iremos:

  • Criar um script capaz de:
    • Listar o data e hora de logon, no Active Directory, do usuário ativo;
    • Obter os data e hora horários (UTC e com timezone);
    • Enviar alerta para o usuário, caso na hora seguinte (do dia atual) existe uma restrição de horário;
    • Bloquear o computador se a hora atual (do dia atual) for uma hora que o usuário tem uma restrição de horário;
  • Salvar esse script em uma pasta compartilhada da rede;
  • Criar uma tarefa agendada para executar esse script enquanto o usuário estiver usando o computador.

Sugerimos que pegue a versão mais atual do nosso código em nosso repositório GitHub, disponível em VBS – Logon_hours – GitHub. Caso prefira criar manualmente, crie um arquivo VBS para esse caso, pois apesar de ser mais simples o código no PowerShell não queremos permitir que usuários possam executar scripts PowerShell’s não assinados (que outros scripts podem conter conteúdo malicioso ou indesejado). Para isso, abra o bloco de notas e coloque o seguinte conteúdo:

On Error Resume Next

'Obtem os dados da conta LDAP
Dim objSysInfo, objUser
Set objSysInfo = CreateObject("ADSystemInfo")
'5 tentativas de conexão ao AD (problemas em laptops em Wifi, logar em cache, mas ainda não tem acesso à rede)
xcount = 0
While xcount < 5
	Set objUser = GetObject("LDAP://" & objSysInfo.UserName)
	If IsNull(objUser) or IsEmpty(objUser) Then
		xcount = xcount+1
		If (xcount = 5) Then
			Wscript.quit
		Else
			Wscript.sleep 3000
		End If
	Else
		xcount = 5
	End If
Wend

If IsNull(objUser.Get("logonHours")) Then
	wscript.quit
End If

arrLogonHours = objUser.Get("logonHours")

Dim arrLogonHoursBytes(20)
Dim Schedule(7,23)
For i = 1 To LenB(arrLogonHours)
     arrLogonHoursBytes(i-1) = AscB(MidB(arrLogonHours, i, 1))
Next

'Obtem a agenda de horarios da conta LDAP
intCounter = 0
For Each LogonHourByte In arrLogonHoursBytes
	arrLogonHourBits = GetLogonHourBits(LogonHourByte)
 	For Each LogonHourBit In arrLogonHourBits
		'Sei que passando 24 horas é outro dia, então vou obter o dia a partir do total de horas dividido por 24
		check_day = intCounter
		'Vou obter a hora DESSE dia pegando o total de horas e subtraindo as horas dos dias anteriores
		check_hour = (intCounter - (check_day*24))
		'wscript.echo "semana " & check_day & " - as " & check_hour & " horas - liberacao: "& LogonHourBit
		Schedule(check_day,check_hour) = LogonHourBit
	        intCounter = 1 + intCounter
	Next
Next

'OBTENDO O DIA DA SEMANA E A HORA EM UTC
Set dateTime = CreateObject("WbemScripting.SWbemDateTime")
dateTime.SetVarDate (now())
This_Moment_UTC = dateTime.GetVarDate (false)
'Vou obter a data futura em uma hora (pois se for 23 horas, vai mudar o dia também)
dateTime.Hours = dateTime.Hours+1
NextHour_UTC = dateTime.GetVarDate (false)
'Vou obter os valores com o timezone local, para usar na hora de exibir a mensagem para o usuário
NextHour_TZ = dateTime.GetVarDate ()
'Defindo todas os dias e horas que usaremos nesse script
Now_Weekday = Weekday(This_Moment_UTC)-1
NextHour_UTC_Weekday = Weekday(NextHour_UTC)-1
Now_Hour_UTC = DatePart("h", This_Moment_UTC)
NextHour_UTC_Hour = DatePart("h", NextHour_UTC)
NextHour_Hour_TZ = DatePart("h", NextHour_TZ)

'VERIFICA SE TEM USUARIO LOGADO
Dim computer, UserIsLogged, wmi
computer = "."
Set wmi = GetObject("winmgmts://" & computer & "/root/cimv2")
UserIsLogged = wmi.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'LogonUI.exe'").Count

'Vamos verificar se o usuário está logado
If NOT (UserIsLogged ) Then
	'Vamos dar alerta se na proxima hora vai acabar o horario de logon OU bloquear se já acabou o tempo
	If Schedule(Now_Weekday,Now_Hour_UTC) = 0 Then
		Set oShell = WScript.CreateObject ("WScript.Shell")
		oShell.run "Rundll32.exe User32.dll,LockWorkStation"
	ElseIf Schedule(Now_Weekday,NextHour_UTC_Hour) = 0 Then
		dim answer
		answer = MsgBox("Sua conta de rede ira bloquear as "& NextHour_Hour_TZ &" horas" & vbcrlf & "" & vbcrlf & "Se for preciso, entre em contato com o suporte",48,"Controle de Logon")
	End If
End If

Function GetLogonHourBits(x)
	Dim arrBits(7)
	For i = 7 to 0 Step -1
		If x And 2^i Then
			arrBits(i) = 1
		Else
			arrBits(i) = 0
		End If
	Next
	GetLogonHourBits = arrBits
End Function

Salve o arquivo com o nome Logon_hours.vbs e teste esse arquivo manualmente em alguns cenários (com uma conta de teste, configurada restrições de horário no Active Directory) para se certificar que está executando corretamente. Em seguida copie para a pasta de rede \\seudominio.com.br\Netlogon

Funcionando tudo corretamente até esse ponto, crie uma política de Grupo/GPO chamada Logon_hours_Restrition e vincule na OU onde estão seus usuários. Edite essa GPO

Crie uma GPO chamada Check Logon Hours, vincule ela na OU que estão os usuários que devem receber essa política de papel de parede. Edite essa GPO e vá em User Configuration , Preferences, Control Panel Settings, Task Scheduler , crie uma nova tarefa agendada para Windows 7 ou superior, na tela de criação a seguinte tarefa agendada:

  • Em General:
    • Em Action, defina como Update
    • Em Name, insira GPO-Check Logon Hours
    • Em Account, insira %LogonDomain%\%LogonUser%
    • Marque: Run only when the user is logged on
  • Em Triggers:
    • Adicione uma trigger com Begin the task: At Logon
    • Adicione uma trigger com Begin the task: 08:00 AM, configurado com repeat every 15 minutes e com for a duration of 1 day
    • Adicione uma trigger com Begin the task: At Unlock
  • Em Actions
    • Adicione uma action, em Program, coloque wscript.exe e em Arguments coloque \\suaempresa.com.br\netlogon\Logon_hours.vbs
  • Clique em OK e feche a GPO.

Em um usuário que possuí restrição de horário, atualize as políticas de grupo (no CMD, com o comando GPUpdate /force) e teste novamente.

Por fim, agora defina as restrições de horários nos usuários que desejar.

Fontes/Referências

https://github.com/luizcarlosbranco/nvlan

https://www.activexperts.com/admin/vbscript-collection/usersgroups/users/#DisplayAllowedLogon.htm

Mais Informações

Esperamos ter te ajudado e estaremos sempre a disposição para mais informações.

Se você tem interesse em algum assunto específico, tem alguma dúvida, precisa de ajuda, ou quer sugerir um post, entre em contato conosco pelo e-mail equipe@nvlan.com.br.

NVLAN - Consultoria