!***********************************************************************
!*
!* Command for changing user passwords
!*
!* Copyright (C) R.D. Eager University of Kent MCMLXXXV
!*
!***********************************************************************
!
!
!***********************************************************************
!*
!* Constants
!*
!***********************************************************************
!
constantinteger minpass = 6; ! Min length of a password
constantinteger maxpass = 11; ! Max length of a password
constantlonginteger int mask = x'0002000A0002000A'
! INT: 'A','C','Q','a','c','q'
constantstring (1) snl = "
"
!
!
!***********************************************************************
!*
!* Subsystem references
!*
!***********************************************************************
!
systemroutinespec console(integer ep,integername start,len)
systemstring (255)mapspec controlline(integername flag)
systemstringfunctionspec itos(integer n)
systemroutinespec journaloff
systemintegerfunctionspec parmap
externalroutinespec prompt(string (255) s)
systemroutinespec psysmes(integer root,mess)
systemroutinespec reroutecontingency(integer ep,class,longinteger c
mask,routine ontrap,
integername flag)
systemroutinespec setfname(string (63) s)
externalroutinespec setmode(string (255) s)
systemroutinespec setpar(string (255) s)
externalroutinespec set return code(integer i)
systemstringfunctionspec spar(integer n)
systemroutinespec signal(integer ep,p1,p2,integername flag)
systemroutinespec uctranslate(integer ad,len)
externalintegerfunctionspec uinfi(integer entry)
externalstringfunctionspec uinfs(integer entry)
!
!
!***********************************************************************
!*
!* Director references
!*
!***********************************************************************
!
externalintegerfunctionspec dsetpassword(string (6)user,integer fsys,
which,string (63) old,new)
!
!
!***********************************************************************
!*
!* Forward references
!*
!***********************************************************************
!
routinespec finalise security
!
!
!***********************************************************************
!*
!* Service routines
!*
!***********************************************************************
!
routine ontrap(integer class,subclass)
integer flag
!
flag = 0
finalise security
signal(3,class,subclass,flag); ! Get the Subsystem to do the rest
end ; ! of ontrap
!
!-----------------------------------------------------------------------
!
routine initialise security(integername flag)
! Intercept single-character INT: messages, so that the security
! precautions may be unset on exit.
!
reroutecontingency(3,65,int mask,ontrap,flag)
if flag = 0 then start
setmode("-E"); ! Turn off input echo
journaloff; ! Turn off any journal
finish
end ; ! of initialise security
!
!-----------------------------------------------------------------------
!
routine finalise security
integer flag,ad
!
setmode("E"); ! Turn on input echo
newline
ad = 0
console(14,ad,ad); ! Turn on recalling again
reroutecontingency(0,0,0,ontrap,flag); ! Cancel contingency rerouting
end ; ! of finalise security
!
!-----------------------------------------------------------------------
!
routine read password(string (63) mes,stringname p,integername flag)
stringname line
!
printstring(mes); newline
prompt(tostring(nl)."Password: ")
line == control line(flag)
newline
if flag # 0 then start
setfname("")
flag = 202; ! Invalid parameter
return
finish
!
p = line
uctranslate(addr(p)+1,length(p))
flag = 0
end ; ! of read password
!
!
!***********************************************************************
!*
!* P A S S W O R D
!*
!***********************************************************************
!
externalroutine password(string (255) parms)
integer flag,i,c,fore,back
string (maxpass) pass1,pass2,oldpass
stringname line
!
! Decode and validate any parameter, after disallowing use in OBEY and
! batch.
!
if uinfi(2) # 1 then start
printstring("Password may only be changed from an interactive terminal")
newline
flag = 173; ! No access permission
-> err3
finish
!
setpar(parms)
if parmap > 1 then start
flag = 263; ! Wrong number of parameters
-> err2
finish
!
parms = spar(1)
uctranslate(addr(parms)+1,length(parms))
line == parms
fore = 0
back = 0
cycle
for i = 1,1,length(line) cycle
c = charno(line,i)
if c = 'F' then fore = -1 else c
if c = 'B' then back = -1 else start
printstring("Parameter not recognised.".snl)
fore = 0
back = 0
exit
finish
repeat
exit if fore + back # 0; ! A valid letter was typed
printstring("Which password do you want to change?".snl)
printstring("(F for foreground, B for background, FB for both)".snl)
prompt("F or B or FB: ")
line == controlline(flag)
if flag # 0 then start
line == parms
line = ""
finish
uctranslate(addr(line)+1,length(line))
repeat
!
! Turn off input echo, and disable the session journal, for obvious
! security reasons.
!
initialise security(flag)
-> err if flag # 0
!
! Read in the current foreground password (needed by DSETPASSWORD)
!
printstring("Passwords will not be echoed.".snl)
read password("Type in your current FOREGROUND password.",oldpass,flag)
-> err if flag # 0
!
! Read the new password(s) twice, and check that they were the same both
! times. It is quite likely that the user will not be sure what he typed
! (since input echo is off), so this helps to ensure that he knows what
! he has set the password(s) to.
!
cycle
if fore # 0 then printstring(snl."Change FORE") else c
if back # 0 then printstring(snl."Change BACK") else c
exit
printstring("GROUND password -".snl)
!
read password("Type in your new password -",pass1,flag)
-> err if flag # 0
!
if length(pass1) < minpass then start
printstring("For security reasons, your password must be at least ".itos(minpass)." characters long".snl)
printstring("Please choose another one".snl)
continue
finish
!
if length(pass1) > maxpass then start
printstring("Passwords may not be more than ".itos(maxpass)." characters long".snl)
printstring("Please choose another one".snl)
continue
finish
!
read password("Please type new password again to confirm -",pass2,flag)
-> err if flag # 0
if pass1 # pass2 then start
printstring("You gave two different forms for your new password.".snl)
printstring("The old password has not been changed.".snl)
exit
finish
!
flag = dsetpassword(uinfs(1),uinfi(1),¬fore,oldpass,pass1)
if fore # 0 then fore = 0 else c
if back # 0 then back = 0
if flag # 0 then start
back = 0
if flag = 8 then start
printstring("You did not give your current foreground")
printstring(" password correctly.".snl)
printstring("The password has not been changed.".snl)
flag = 173; ! No access permission
-> err4
finish else start
flag = flag + 500
-> err
finish
finish
oldpass = pass1
printstring("Password changed.".snl)
repeat
!
err:
finalise security
if flag = 1000 then start
printstring("The password you typed was too long.".snl)
printstring("Passwords may not be more than ".itos(maxpass)." characters long.".snl)
-> err4
finish
!
err2:
if flag # 0 then psysmes(63,flag)
!
err3:
set return code(flag)
return
!
err4:
finalise security
-> err3
end ; ! of password
endoffile