Categories
Programming

VAX/VMS MACRO password checker

The following is come code I found I wrote many years ago in Digital VAX MACRO to check passwords for a particular username against a dictionary of words concatenated with a number.

.title    check_password

$rmsdef
$uaidef

.psect    rw_data rd,wrt,noexe,noshr,long

pwdlist_fab:    $fab    fnm = <sys$library:VMS$PASSWORD_DICTIONARY.DATA>

pwdlist_rab:    $rab    fab = pwdlist_fab,-
rop = rah,-
ubf = rec_buff,-
usz = rec_size

rec_size = 32
rec_desc:    .word    rec_size
.word    0
.address rec_buff
rec_buff:    .blkb    rec_size

cur_count:    .long
max_count = 99
num_size = 2
cur_no:        .ascid    \99\

cur_pwd:    .word   rec_size+num_size
.word    0
.address 10$
10$:        .blkb    rec_size+num_size

cur_hash:    .blkb    8

username:
username_len:    .word    12
.word    0
.address 10$
10$:        .blkb    12

pwd_list:    .word    1
.word    uai$_encrypt
.address encrypt
.address encrypt_len
.word    8
.word    uai$_pwd
.address pwd
.address pwd_len
.word    2
.word    uai$_salt
.address salt
.address salt_len
.word    0
.word    0
encrypt:    .byte
encrypt_len:    .word
pwd:        .blkb    8
pwd_len:    .word
salt:        .word
salt_len:    .word

usage_msg:    .ascid \VMS username must be specificed as a parameter\

.psect    code rd,nowrt,exe,shr,long

.entry    check_password,^m<>

; get username passed on command line - display error if not present

pushaq    username
calls    #1,g^lib$get_foreign
blbc    r0,error_exit
pushaw    username_len
pushaq    username
pushaq    username
calls    #3,g^str$trim
blbc    r0,error_exit
tstw    username_len
bnequ    get_pwd
pushaq    usage_msg
calls    #1,g^lib$put_output
brb    normal_exit

; retrieve the hashed password from the UAF file

get_pwd:    $getuai_s usrnam=username,-
itmlst=pwd_list
blbc    r0,error_exit

; open the VMS password dictionary

open_dic:    $open    fab=pwdlist_fab
blbc    r0,error_exit
$connect rab=pwdlist_rab
blbc    r0,error_exit

; retrieve a word from the dictionary

word_loop:    $get    rab=pwdlist_rab
blbs    r0,remove_nulls
cmpl    r0,#rms$_eof
beql    normal_exit
brb    error_exit

; get rid of nulls on the end of the record and convert to uppercase

remove_nulls:    clrw    r1
movaq    rec_buff,r2
10$:        tstb    (r2)
beql    20$
incw    r1
incl    r2
brb    10$
20$:        movw    r1,rec_desc
pushaq    rec_desc
pushaq    rec_desc
calls    #2,g^str$upcase

; start back at zero for new word

clrl    cur_count

; append a number to the word

append_no:    pushl    #2
pushl    #1
pushaq    cur_no
pushal    cur_count
calls    #4,g^ots$cvt_l_tu

movw    #rec_size+num_size,cur_pwd
pushaq    cur_no
pushaq    rec_desc
pushaq    cur_pwd
calls    #3,g^str$concat
blbc    r0,error_exit

pushaw    cur_pwd
pushaq    cur_pwd
pushaq    cur_pwd
calls    #3,g^str$trim

; now we have all the info to hash a password

$hash_password_s -
pwd=cur_pwd,-
alg=encrypt,-
salt=salt,-
usrnam=username,-
hash=cur_hash
blbc    r0,error_exit

; check if we have a match on the hashed password - if so display

cmpl    cur_hash,pwd
bneq    no_match
cmpl    cur_hash+4,pwd+4
bneq    no_match
pushaq    cur_pwd
calls    #1,g^lib$put_output
brb    normal_exit

; loop back 'max_count' times

no_match:    aoblss    #max_count,cur_count,append_no

; loop back for another word

brb    word_loop

normal_exit:    movl    #1,r0
error_exit:    ret

.end    check_password