home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 September / Simtel20_Sept92.cdr / msdos / sysutl / passwrd5.arc / PASSWRD5.ASM < prev    next >
Assembly Source File  |  1988-09-20  |  12KB  |  383 lines

  1. PAGE 60,132
  2. TITLE PASSWRD5.ASM - PASSWRD5.SYS DEVICE DRIVER
  3. ;------------------------------------------------------------
  4. ;[from SIMTEL20's PD:<MSDOS.SYSUTL>PASSWORD.ARC, tweaked]
  5.  
  6. ;PASSWRD5.ASM (CREATES PASSWRD5.SYS, DEVICE DRIVER)
  7. ;DOS 2.00 DEVICE DRIVER FORCES USER TO ENTER PASSWORD ON BOOTING UP
  8. ;AND DISABLES Ctrl-Break.
  9. ;
  10. ;v1.5 19 Sep 88
  11. ; - Got a msg from Bernie Eiben, explaining what's going on with the Init
  12. ;   procedure and why the code got overlaid/garbaged on installation.
  13. ;   Turns out I did good in moving Ask_Off up in the code (even tho
  14. ;   I didn't know why).  Comments edited and clarified.
  15. ; - Added version number to the device_name
  16. ; - Let the compiler compute password length, password space padding
  17. ;David Kirschbaum
  18.  
  19. ;v1.4 Toad Hall Tweak, 7 Aug 88
  20. ; - Tightened code a little.
  21. ; - changed "ESC" to "ESCP" so MASM 5.0 wouldn't complain.
  22. ; - Reorganized to put things more inline, keep FAR things FAR.
  23. ;David Kirschbaum
  24. ;Toad Hall
  25. ;kirsch@braggvax.ARPA
  26.  
  27. ; REV by JOHN R. PETROCELLI   02/25/85
  28. ;
  29. ; ADDITIONAL CODE HAS BEEN ADDED TO INITIALIZE INT 66h WITH THE
  30. ; SEGMENT AND OFFSET OF THE "RECALL" CODE (Ask_Off). USING THE
  31. ; PROGRAM "LOCK.COM" WILL ENABLE THE USER TO DISABLE THE USE OF THE
  32. ; PC UNTIL THE CORRECT PASSWORD IS SUPPLIED.
  33. ;
  34. ;AFTER ASSEMBLY: LINK PASSWRD5 (ignore "no STACK" error)
  35. ;         EXE2BIN PASSWRD5 PASSWRD5.SYS
  36. ;         (Or use one of the public domain EXE2COM utilities,
  37. ;         insuring any product is a .SYS type.)
  38. ;         Place DEVICE=PASSWRD5.SYS in CONFIG.SYS file
  39. ;         Reboot system with Ctrl-Alt-Del
  40. ;         Answer prompt with : Password <ENTER>
  41. ;         **** BEWARE OF UPPER VS LOWER CASE ****
  42. ;
  43.  
  44. DEV_SEG SEGMENT
  45.     ASSUME CS:DEV_SEG, DS:DEV_SEG, ES:DEV_SEG
  46.     org    0        ;TH
  47.  
  48. Pword_Device PROC FAR
  49.  
  50. ;---------------------------------------------------------------
  51. ;The following lines are the device header, which must exist for
  52. ;every device. This file has only one device, and it works with
  53. ;character I/O. It doesn't actually handle any I/O services,
  54. ;but it's easier to create a character device.
  55.  
  56. pword_dev_header    label    byte    ;start of the device driver
  57.  
  58. next_dev_ptr    DD  -1        ;only 1 device is defined in this file
  59. dev_attribute    DW  1000000000000000B
  60. strategy_ptr    DW  Strategy    ;the installation procedure
  61. interupt_ptr    DW  Interupt    ;the proc that handles all services
  62. device_name    DB  'PWORD15'    ;device name string (up to 8 bytes)
  63.  
  64. ; -- This is the storage area for the password --
  65. ; -- The first byte is the length (0-16) --------
  66. ; -- The following characters are the password --
  67. ; -- Only an exact match will allow the system --
  68. ; -- to continue the boot process ---------------
  69.  
  70. ;TH 1.5 A note to operators:  If you just HAVE to find the password in
  71. ;the installed driver or PASSWRD5.SYS file .. use DEBUG or a binary file
  72. ;editor like FM (or even Buerg's LIST.COM in hexidecimal mode).  Look
  73. ;immediately after the device_name "PWORD15" (8 bytes altogether), and
  74. ;you should see the hardcoded password.
  75. ;THIS is what makes this sucker "not so very secure."
  76. ;So don't tell the users!
  77. ;
  78. password_store    DB    LEN        ;v1.5 actual password length
  79.         db    'plan'        ;actual password (case matters!)
  80.                     ;(replace with yours, up to 16 chars)
  81. ;Leave room for a 16-character password
  82. LEN    equ    $-password_store-1    ;v1.5
  83.         DB    16-LEN DUP(' ')    ;v1.5 pad with spaces (unused)
  84.  
  85. inbuf_max    DB    16        ;max password length allowed
  86. inbuf_len    DB    0        ;actual keyboard entry length
  87. inbuf        DB    16 DUP(0)    ;TH buffer for keyboard input
  88.  
  89. break_off    DW    0        ;TH save old Int 1BH vector
  90. break_seg    DW    0        ;TH
  91.  
  92. ; -- The Strategy proc stores ES:BX request header pointer here
  93. ; -- The Interupt proc retrieves it
  94.  
  95. request_ptr    LABEL    DWORD
  96. req_ptr_off    DW    0        ;TH
  97. req_ptr_seg    DW    0        ;TH
  98.  
  99. ;dummy_iret    DB    207    ;Ctrl-Break vector is pointed here, so it
  100.                 ;does nothing. Break is not recognized!
  101.                 ;TH this is actually an IRET instruction.
  102. dummy_iret:    IRET        ;TH v1.5
  103.  
  104. ;---------------------- Messages ----------------------------------
  105. ;These messages are expected to be output via the ANSI.SYS device,
  106. ;so it should be installed (named in the CONFIG.SYS file) before
  107. ;this PWORD device.
  108. ;If you don't want to use ANSI.SYS, remove the ESCP sequences in the
  109. ;messages.
  110.  
  111. ANSI    EQU    1            ;v1.5 make 0 for non-ANSI display
  112.  
  113. LF    EQU    0AH
  114. CR    EQU    0DH
  115. ESCP    EQU    1BH
  116.  
  117.     IF    ANSI            ;v1.5
  118.  
  119. msg_1    DB    CR,LF,ESCP,'[0m'    ;make output visible
  120.     DB    'Enter '
  121.     DB    ESCP,'[5m'        ;make output blink
  122.     DB    'Password: '
  123.     DB    ESCP,'[8m$'        ;make input invisible
  124.  
  125. msg_2    DB    CR,LF,ESCP,'[0m'    ;make output visible
  126.     DB    'Password accepted.',CR,LF,'$'
  127.  
  128.     ELSE                ;v1.5
  129.  
  130. msg_1    DB    CR,LF,'Enter Password: $'
  131.  
  132. msg_2    DB    CR,LF,'Password accepted.',CR,LF,'$'
  133.  
  134.     ENDIF                ;v1.5
  135.  
  136. Pword_Device    endp            ;TH
  137.  
  138. ;====================================================================
  139. ;Strategy procedure
  140. ;Just saves the request header pointer for the Interupt proc
  141.  
  142. Strategy PROC FAR
  143.     ASSUME    CS:DEV_SEG
  144.     MOV    CS:req_ptr_off,BX
  145.     MOV    CS:req_ptr_seg,ES
  146.     RET
  147. Strategy ENDP
  148.  
  149. ;====================================================================
  150.  
  151. No_Break PROC NEAR
  152.  
  153. ;The following 8 lines eliminate Ctrl-Break from having any effect
  154. ;on the system, unless another program KEYBOARD_BREAK vector is
  155. ;altered (BASIC does that).
  156. ; OLD BREAK VECTOR IS STORED SO THAT IT MAY BE RESET
  157.  
  158.     ASSUME    DS:DEV_SEG,ES:Nothing    ;TH a reminder
  159.  
  160.     xor    ax,ax            ;TH
  161.     MOV    ES,AX
  162.     MOV    AX,WORD PTR ES:[1Bh*4]    ;save old Int 1BH
  163.     MOV    break_seg,AX
  164.     MOV    AX,WORD PTR ES:[1Bh*4+2]
  165.     MOV    break_off,AX
  166.     MOV    WORD PTR ES:[1Bh*4],OFFSET dummy_iret    ;reset to our function
  167.     MOV    WORD PTR ES:[(1Bh*4)+2],CS    ;(a dummy IRET)
  168.     RET
  169.  
  170. No_Break ENDP
  171.  
  172. Break_On  PROC NEAR
  173.  
  174. ; THE FOLLOWING 6 LINES RESTORE THE CTL-BREAK VECTOR
  175.  
  176.     xor    ax,ax            ;TH
  177.     MOV    ES,AX
  178.     MOV    AX,break_seg        ;Restore the Int 1BH seg
  179.     cli                ;TH let's try this
  180.     MOV    WORD PTR ES:[1Bh*4],AX    ;restore the segment
  181.     MOV    AX,break_off        ; and offset
  182.     MOV    WORD PTR ES:[(1Bh*4)+2],AX
  183.     sti                ;TH restore ints
  184.     RET
  185.  
  186. Break_On  ENDP
  187.  
  188. ;====================================================================
  189. Ask_Pwrd    PROC NEAR
  190. ;
  191. ; This code prompts the user for the correct password
  192. ;
  193.     mov    ax,CS
  194.     mov    ES,ax            ;TH for string comparisons
  195.     ASSUME    DS:DEV_SEG, ES:DEV_SEG    ;TH a reminder
  196.  
  197. Try_Again:
  198.     mov    ax,0E07H        ;TH write a beep TTY
  199.     INT    10H
  200.     MOV    DX,OFFSET msg_1        ;"Enter Password: "
  201.     MOV    AH,9            ;DOS display msg
  202.     INT    21H
  203.  
  204.     MOV    DX,OFFSET inbuf_max    ;TH keyboard input buffer
  205.     mov    ax,0C0AH        ;TH buffered kbd input
  206.     INT    21H
  207.  
  208.     MOV    SI,OFFSET inbuf_len    ;nr chars he typed
  209.     MOV    DI,OFFSET password_store ;our password length
  210.     xor    ch,ch            ;clear msb
  211.     MOV    CL,[SI]            ;compare his input length..
  212.     CMP    CL,[DI]            ;.. to our password length
  213.     JNE    Try_Again        ;not the same .. gotta be wrong
  214.     INC    DI            ;bump past length bytes
  215.     INC    SI
  216.     REP    CMPSB            ;do a comparison
  217.     JNE    Try_Again        ;not the same .. dummy
  218.  
  219.     MOV    DX,OFFSET msg_2        ;"Password accepted"
  220.     MOV    AH,9            ;DOS display msg
  221.     INT    21H
  222.  
  223.     RET
  224.  
  225. Ask_Pwrd    ENDP
  226.  
  227. Ask_Off    proc    far            ;TH
  228.  
  229.     push    ax        ;TH do this same order as Init_Fn above
  230.     push    bx
  231.     push    ES
  232.     push    cx
  233.     push    dx
  234.     push    si
  235.     push    di
  236.     push    DS
  237.  
  238.     MOV    AX,CS
  239.     MOV    DS,AX
  240.  
  241.     CALL    No_Break        ;turn Ctrl C function off
  242.  
  243.     CALL    Ask_Pwrd        ;Try for the password
  244.  
  245.     CALL    Break_On        ;turn Ctrl C function back on
  246.  
  247. Exit:
  248.     pop    DS            ;clean up the stack
  249.     pop    di
  250.     pop    si
  251.     pop    dx
  252.     pop    cx
  253.     pop    ES            ;the ones we first pushed
  254.     pop    bx
  255.     pop    ax
  256.     ret                ;RET FAR from drivers
  257. Ask_Off    endp                ;TH
  258.  
  259. ;=====================================================================
  260. ;Interupt procedure
  261. ;Processes the command indicated in the request header.
  262.  
  263. Interupt PROC FAR
  264.     ASSUME CS:DEV_SEG, DS:NOTHING, ES:NOTHING
  265.  
  266.     push    ax            ;TH save only what we need
  267.     push    bx            ;TH for first test
  268.     push    ES
  269.     LES    BX,request_ptr        ;vector to our request flag
  270.     MOV    AL,ES:[BX+2]        ;check the init byte
  271.     or    al,al            ;TH 0 means not initialized
  272.     je    Init_Fn            ;TH so go initialize
  273.  
  274.     OR    WORD PTR ES:[BX+3],8003H    ;the word right after
  275.     pop    ES            ;TH restore those we disturbed
  276.     pop    bx
  277.     pop    ax
  278.     ret                ;RET FAR from drivers
  279. Interupt    endp            ;TH
  280.  
  281.  
  282. ;TH An explanation .. When I first tweaked PASSWRD, it would compile,
  283. ;load, run on system boot, and even prompt for and process the password.
  284. ;However, the LOCK.COM utility (which calls Ask_Off) would lock up!
  285. ;Turned out Ask_Off was low in the original code (below Init_Fn), and its
  286. ;code space was being released and overwritten after PASSWRD initialized.
  287. ;LOCK.COM had no Ask_Off to call!
  288. ;
  289. ;I fixed this in PASSWRD4 by moving Init_Fn higher in the code
  290. ;(but I didn't understand what was going on).
  291. ;Thanks to Bernie Eiben for explaining what was happening with the
  292. ;Init process.  (See his message at the end of this source code.)
  293.  
  294. Init_Fn PROC    FAR    ;was NEAR
  295.     push    cx            ;TH already pushed ax,bx,ES
  296.     push    dx            ;TH so gotta save the rest now
  297.     push    si
  298.     push    di
  299.     push    DS
  300.  
  301.     PUSH    ES            ;TH yep, save ES again since the
  302.                     ; Break fiddling'll blast it
  303. ;TH I'm assuming DOS initialized DS to CS on loading.
  304.  
  305.     CALL    No_Break        ;Turn Ctrl C function off
  306.  
  307.     CALL    Ask_Pwrd        ;Get user password
  308.  
  309.     CALL    Break_On        ;Turn Ctrl C function back on
  310.  
  311.     POP    ES            ;restore ES vector to installed driver
  312.  
  313. ;TH v1.5:  I'm not exactly sure what's happening here .. I THINK we're
  314. ;leaving information for DOS to release everything from Init_Fn on (e.g.,
  315. ;FREEMEM equivalent).  The Init_Fn function is only used once, and then
  316. ;will be overlaid by later drivers, DOS, whatever.  (Again, thanks to
  317. ;Bernie Eiben for the explanation.  No, STILL haven't done a thorough
  318. ;study of DOS device drivers .. sigh ..)
  319.  
  320.     MOV    WORD PTR ES:[BX+0EH],OFFSET Init_Fn    ;release from here on
  321.     MOV    WORD PTR ES:[BX+10H],CS
  322.  
  323.     OR    WORD PTR ES:[BX+3],0100H    ;flag we're initialized?
  324.  
  325. ; THE FOLLOWING 6 LINES SET THE REFERENCE FOR RECALL.
  326. ; LOCATION AT INT 66H IS USED FOR ADDRESS STORE
  327. ;TH: I donno about this .. isn't anyone else using Int 66H?
  328. ;I'd rather have LOCK.COM search through memory for THIS particular
  329. ;driver (by finding its name or something).
  330. ;Think about that later if anything conflicts.
  331.  
  332.     xor    ax,ax                ;TH
  333.     MOV    ES,AX                ;page 0
  334.     MOV    AX,CS
  335.     MOV    DS,AX
  336.     ASSUME    DS:DEV_SEG, ES:Nothing        ;TH a reminder
  337.  
  338. ;Point Int 66H to our Ask_Off routine.
  339.     MOV    AX,OFFSET Ask_Off
  340.     MOV    WORD PTR ES:[66H*4],AX
  341.     MOV    WORD PTR ES:[66H*4+2],CS    ;TH
  342.  
  343.     jmp    Exit                ;TH common pop, return
  344. Init_Fn  ENDP
  345.  
  346. DEV_SEG  ENDS
  347.     END Pword_Device
  348.  
  349. From EIBEN@TOPS20.DEC.COM Mon Sep  5 10:54:15 1988
  350. Date: 5 Sep 1988 1053-EDT
  351. From: EIBEN@TOPS20.DEC.COM
  352. To: David Kirschbaum <kirsch@braggvax.arpa>
  353. Message-Id: <"MS11(6041)+GLXLIB6(0)" 12428147514.13.41.10070 at TOPS20.DEC.COM>
  354. References: Message from David Kirschbaum <kirsch@braggvax.arpa>
  355.               of 27-Jul-88 1039-EDT
  356. In-Reply-To: <8807271223.AA22884@braggvax.arpa>
  357.  
  358. Just saw Your PASSWRD4.ARC - and the 'dunno' comment in INIT_FN [or something
  359. close].. Thats standard documented DOS behaviour.
  360.  
  361. to quote..
  362. One of the functions defined for each device is INIT. This routine is called
  363. only once when the device is installed and never again. The INIT routine
  364. returns the following:
  365.  
  366.     A location to the first free byte of memory after the device driver,
  367.     like a terminate and stay resident that is stored in the ending address
  368.     field. This way the initialization code can be used once and thrown
  369.     away to save space.
  370.  
  371.     After setting the ending address field, a character device driver can
  372.     set the status word and return.
  373.  
  374. [quoted without permission from Technical Reference, Disk Operating System
  375.  Version 3.30 , IBM]
  376.  
  377. Rgds,
  378. Bernie - You might want to 'remove' Your comments - the code does the
  379.      'correct' thing - it removes the INIT piece by letting DOS
  380.      're-use' the space... maybe a comment BEFORE INIT should warn,
  381.      that the 'following' is overlaid 'once-only' code.
  382.    --------
  383.