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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
.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