Wednesday, January 23, 2008

Batch script userinput checking

I have to run a script with the runas command, but since the script is running commands toward several servers there is the danger of locking out the runas user if the password given is wrong. Simply because runas does not verify the password, it just executes the commands.

So to avoid problems I would like to ask the user for the password, verify the password, and only actually run the runas command if the password is as expected.

At a first glance this sounded good, I just had to put in the checksum of the expected userinput in the script, then calculate the checksum of the userinput, and compare the two inside the script.

At second thought this solution was not really acceptable, because if the users password changes, you would have to update the script! Not very robust or elegant. So instead a colleague pointed out the obvious, which of course is to check errorlevel of a single run of runas. That should not lock out the user:
runas /user:domain\username net >nul 2>&1
if not errorlevel 0 (set status=failure & goto exiting)


To make any of above approaches work, we needed a method of getting users input, and a method of sending that input to runas.

Getting the users input in a .batch file was solved by using a special .com file:
echo hP1X500P[PZBBBfh#b##fXf-V@`$fPf]f3/f1/5++u5>%inputfile%
echo Enter a string (it will not echo here):
for /f "tokens=*" %%i in ('%inputfile%') do set userinput=%%i
if "%userinput%"=="" (set status=stringempty & goto exiting)
if "%userinput%"=="^C" (set status=stringcancel & goto exiting)


Sending the %userinput% content back to runas could not be done with a redirection like <, so a mini vbscript for pasting a string was made: Set oArgs=wscript.Arguments
WScript.sleep(1000)
Set WshShell = CreateObject("WScript.Shell")
WshShell.SendKeys oArgs(0)&VBCRLF


Others have been discussing how to pipe passwords into runas, but i dont want to use the approaches described.

So problem was solved without using hardcodet md5 or sha256 checksums! But just to have the hardcoded approach for optional other use, here is how it was done:
FOR /F "usebackq" %%A IN (`echo %userinput% ^| md5deep.exe`) DO set md5hash=%%A
echo debug: md5hash of userinput is: %md5hash%
if "%md5hash%" == "77e2d91aa21a4158d889fb9836f38288" (set status=ok_string_is_hej & goto dosomething)
if "%md5hash%" == "291013bf3a3c543625a2777073f91799" (set status=ok_string_is_password & goto dosomething)

In the above i used md5deep to calculate a checksum of the batch string, and it could easily have been sha256deep.exe which is part of md5deep package.

I would have used Microsofts own Windows checksum util FCIV (FILE CHECKSUM INTEGRITY VERIFIER), but there are at least 2 problems with the current version 2.05:

First, fciv.exe does not take input from STDIN, which means you can not run like this:
echo foobar | fciv.exe

You have to echo into a file and then calculate the checksum:
echo foobar > foobar.txt
fciv.exe foobar.txt
//
// File Checksum Integrity Verifier version 2.05.
//
5e963b88334c3c4487572cce68496989 foobar.txt

So I used md5deep package, which actually does calculate checksum of input from stdin, useful for strings:
echo foobar | sha256deep.exe
791132eb55910a285d5bfeae94b49ead8d5184d7ecf70bccdeafd0e456c2916d
echo foobar | md5deep.exe
5e963b88334c3c4487572cce68496989


The second problem with fciv.exe is the output: it is too verbose! I would need only the checksum so I can put it into a variable. So md5deep it is!

The trick to actually get the output from external md5deep command into a batch variable, is to use a for loop, and escape the pipe () with a ^ instead of a \ which was what I tried first.

Apparently the hat (^) is the dos char for escaping, eg. used if you want to echo the following characters from a .batch file into another file: ^@, ^> and ^&. For example:
echo ^@echo off > c:\tempscript.bat
echo dir c:\ ^> c:\dirlist.txt >> c:\tempscript.bat
echo del c:\tempfile.log /F /Q >> c:\tempscript.bat
echo exit >> c:\tempscript.bat


Another md5 sum checker, built in java (source available), which can check a dir and subdirs, like md5deep.exe can be found here.

1 comment:

daspeac said...

I have heard about another way of program repair pdf to work at acrobat. Besides, you can visit my blogs at: http://daspeac.livejournal.com/ or http://daspeac.blogspot.com/ where I’m trying to share my experience with regard to data corruption issues.