From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CUNYVM.CUNY.EDU::VMSSERV%FHCRCVAX.BITNET" 24-OCT-1989 10:30
To:	MRGATE::"ARISIA::EVERHART"
Subj:	VMSSERV_ROOT:[FILES]UAF.2_OF_3;1

Message-Id:  <8910241408.AA03207@crdgw1.ge.com>
Received: from UWAVM.ACS.WASHINGTON.EDU by UWAVM.ACS.WASHINGTON.EDU (IBM VM SMTP R1.2.1MX) with BSMTP id 7235; Tue, 24 Oct 89 07:11:23 PDT
Received: from FHCRCVAX.BITNET (VMSSERV) by UWAVM.ACS.WASHINGTON.EDU (Mailer
 R2.04) with BSMTP id 8043; Tue, 24 Oct 89 07:11:14 PDT
Date: Tue, 24 Oct 89 07:01 PST
From: VMSSERV%FHCRCVAX.BITNET@UWAVM.ACS.WASHINGTON.EDU
Subject: VMSSERV_ROOT:[FILES]UAF.2_OF_3;1
To: everhart@arisia.decnet
X-Vms-To: IN%"everhart%arisia.decnet@crdgw1.ge.com"

+-+-+-+ Beginning of part 2 +-+-+-+
X;*  TRANSFERRED.`009`009`009`009`009`009`009    *
X;*`009`009`009`009`009`009`009`009`009    *
X;*  THE INFORMATION IN THIS SOFTWARE IS  SUBJECT TO CHANGE WITHOUT NOTICE   *
X;*  AND  SHOULD  NOT  BE  CONSTRUED AS  A COMMITMENT BY DIGITAL EQUIPMENT   *
X;*  CORPORATION.`009`009`009`009`009`009`009    *
X;*`009`009`009`009`009`009`009`009`009    *
X;*  DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE  OR  RELIABILITY OF ITS   *
X;*  SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.`009`009    *
X;*`009`009`009`009`009`009`009`009`009    *
X;*`009`009`009`009`009`009`009`009`009    *
X;****************************************************************************
V                                                                           `0
X32
X;++
X; FACILITY: User Verification Subroutine
X;
X; ABSTRACT:
X;
X; ENVIRONMENT:
X;
X; AUTHOR: H. M. Levy`009, CREATION DATE: 20-Sep-1977
X;
X; MODIFIED BY:
X;
X;`009   X-2`009DDP0282`009`009Derrell D. Piper`009   20-APR-1988  13:58
X;`009`009Only test low word of password descriptor.  Otherwise, a
X;`009`009descriptor with TYPE/CLASS information filled in will confuse
X;`009`009this routine.  While it is reasonable to ignore the TYPE/CLASS
X;`009`009information, we shouldn't assume that it is zero.
X;
X;`009V03-002`009SHZ0002`009`009Stephen H. Zalewski,`00902-Mar-1984
X;`009`009If zero length password is passed in, return a null password.
X;`009`009If PURGY_V algorithm used, add check to prevent us from searching
X;`009`009beyond length of username buffer.
X;
X;`009V03-001`009SHZ0001`009`009Stephen H. Zalewski`00914-Feb-1984
X;`009`009Add support for PURDY and PURDY_V encryption.
X;
X;--
X`032
X.SBTTL`009DECLARATIONS
X`032
X;
X; MACROS:
X;
X`032
X.macro`009pushq`009Src
X`009movq`009Src,-(sp)
X.endm
X.macro`009popq`009Dst
X`009movq`009(sp)+,Dst
X.endm
X`032
X;
X; EQUATED SYMBOLS:
X;
X`032
X`009OUTDSC = 4`009`009`009; adr of encrypted output descriptor
X`009PWDDSC = OUTDSC + 4`009`009; adr of password descriptor
X`009ENCRYPT = PWDDSC + 4`009`009; encryption algorithm index (byte)
X`009SALT = ENCRYPT + 4`009`009; random number (word)
X`009USRDSC = SALT + 4`009`009; adr of username descriptor
X`032
X;
X; OWN STORAGE:
X;
X`032
X.psect`009_LIB$CODE`009RD,NOWRT,PIC,SHR,BYTE,EXE
X`032
X;
X; AUTODIN-II polynomial table used by CRC algorithm
X;
X`032
XAUTODIN:
V`009.LONG`009`094O00000000000,`094O03555610144,`094O07333420310,`094O04666230
X254
V`009.LONG`009`094O16667040620,`094O15332650764,`094O11554460530,`094O12001270
X474
V`009.LONG`009`094O35556101440,`094O36003711504,`094O32665521750,`094O31330331
X614
V`009.LONG`009`094O23331141260,`094O20664751324,`094O24002561170,`094O27557371
X034
X`032
X`032
X; The following table of coefficients is used by the Purdy polynomial
X; algorithm.  They are prime, but the algorithm does not require this.
X`032
XC:`009.long`009-83,`009-1`009`009; C1
X`009.long`009-179,`009-1`009`009; C2
X`009.long`009-257,`009-1`009`009; C3
X`009.long`009-323,`009-1`009`009; C4
X`009.long`009-363,`009-1`009`009; C5
X`032
X.SBTTL`009Dispatch - select encryption algorithm
X`032
X;++
X;
X; FUNCTIONAL DESCRIPTION:
X;
X;`009Smash up the password into a non-reversable number.
X;
X; CALLINGS SEQUENCE:
X;
X;`009CALLS/CALLG
X;
X; INPUTS:
X;
X;`009PWDDSC - Address of password descriptor
X;`009ENCRYPT - Encryption algorithm index (byte)
X;`009SALT - random number (word)
X;`009USRDSC - Address of username descriptor
X;
X; IMPLICIT INPUTS:
X;
X;`009none
X;
X; OUTPUTS:
X;
X;`009OUTDSC - Address of output buffer descriptor
X;
X; IMPLICIT OUTPUTS:
X;
X;`009none
X;
X; ROUTINE VALUE:
X;
X;`009Success status
X;
X; SIDE EFFECTS:
X;
X;`009none
X;--
X`032
X.entry`009LGI$HPWD,`094M<r2,r3,r4,r5,r6>`009; entry mask
X`032
X`009tstb`009ENCRYPT(ap)`009`009; using CRC algorithm?
X`009beql`00920$`009`009`009; yes, no processing of user desc necessay.
X`009subl2`009#20,sp`009`009`009; Get temp desc and buffer off stack
X`009movl`009sp,r6`009`009`009; Put address into r6
X`009movq`009@USRDSC(ap),(r6)`009; Put current user desc into stack desc.
X`009cmpb`009#1,ENCRYPT(ap)`009`009; Which PURDY algorithm?
X`009bneq`00910$
V`009movc5`009(r6),@4(r6),#32,#12,8(r6) ; PURDY. 12 character blank pad userna
Xme
X`009movw`009#12,(r6)`009`009; size of desc is now 12
X`009movab`0098(r6),4(r6)`009`009; Point desc to buffer on stack.
X`009brb`00920$`009`009`009; goto main line
X`032
X`009`009`009`009`009; PURDY_V. Remove padding from username.
X10$:`009movzwl`009(r6),r5`009`009`009; Save length of username in r5.
X`009clrw`009(r6)
X`009movl`0094(r6),r0`009`009; Get address of username buffer into R0.
X15$:`009cmpb`009(r0)+,#32`009`009; Search until we find first blank.
X`009beql`00920$
X`009incw`009(r6)`009`009`009; Increment byte count until blank found
X`009cmpw`009#31,(r6)`009`009;  or 31 characters have been encountered
X`009beql`00920$`009`009`009;   (31 is max username length).
X`009cmpw`009r5,(r6)`009`009`009;  or entire buffer has been parsed.
X`009beql`00920$`009`009`009;   (someone not playing by the rules)
X`009brb`00915$
X`032
X20$:`009movaq   @PWDDSC(ap),r4`009`009; If password is zero length
X`009tstw`009(r4)`009`009`009;  (only check low word)
X`009bneq`00925$
X`009movaq`009@OUTDSC(ap),r4`009`009; Then return null password
X`009clrw`009(r4)
X`009movc5`009#0,(r4),#0,#8,@4(r4)`009; (quadword of zeros)
X`009brb 40$
X`032
X25$:`009movaq`009@OUTDSC(ap),r4`009`009; Get pointer to output buffer
X`009movaq`009@4(r4),r4
X`009tstb`009ENCRYPT(ap)`009`009; Use the CRC algorithm if the index
X`009bgtru`00930$`009`009`009; is zero
X`009mnegl`009#1,r0`009`009`009; initial CRC
X`009movaq`009@PWDDSC(ap),r1`009`009; get descriptor address
X`009crc`009AUTODIN,r0,(r1),@4(r1)`009; convert password to 32-bit number
X`009clrl`009r1`009`009`009; high order longword will be zero
X`009movq`009r0,(r4)`009`009`009; copy result to the output buffer
X`009brb`00940$
X`032
X30$:`009clrq`009(r4)`009`009`009; Initialize output buffer
X`009movaq`009@PWDDSC(ap),r3`009`009; Collapse password to a quadword
X`009bsbb`009COLLAPSE_R2
X`009addw2`009SALT(ap),3(r4)`009`009; Add random salt into middle of U
X`009movl`009r6,r3`009`009`009; Collapse username into the quadword
X`009bsbb`009COLLAPSE_R2
X`009pushaq`009(r4)`009`009`009; Push pointer to U
X`009calls`009#1,Purdy`009`009; Run U through the polynomial mod P
X`032
X40$:`009movl`009#1,r0
X`009ret
X`032
XCOLLAPSE_R2:
X.enabl`009LSB
X; This routine takes a string of bytes (the descriptor for which is pointed
X; to by r3) and collapses them into a quadword (pointed to by r4).  It does
X; this by cycling around the bytes of the output buffer adding in the bytes
X; of the input string.
X`032
X`009movzwl`009(r3),r0`009`009; Obtain the number of input bytes
X`009beqlu`00920$
X`009moval`009@4(r3),r2`009; Obtain pointer to input string
X10$:`009bicl3`009#-8,r0,r1`009; Obtain cyclic index into output buffer
X`009addb2`009(r2)+,(r4)[r1]
X`009sobgtr`009r0,10$`009`009; Loop until input string is exhausted
X20$:`009rsb
X.dsabl`009LSB
X`032
X.sbttl`009Purdy - evaluate Purdy polynomial
X`032
Xa=59`009`009`009`009; 2`09464 - 59 is the biggest quadword prime
X`032
Xn0=1@24 - 3`009`009`009; These exponents are prime, but this is
Xn1=1@24 - 63`009`009`009; not required by the algorithm.
X`032
X.entry`009Purdy,`094M<r2,r3,r4,r5>
X;
X; This routine computes f(U) = p(U) mod P.  Where P is a prime of the form
X; P = 2`09464 - a.  The function p is the following polynomial:
X; X`094n0 + X`094n1*C1 + X`0943*C2 + X`0942*C3 + X*C4 + C5
X; The input U is an unsigned quadword.
X;
X`032
X`009pushq`009@4(ap)`009`009; Push U
X`009bsbw`009PQMOD_R0`009; Ensure U less than P
X`009movaq`009(sp),r4`009`009; Maintain a pointer to X
X`009movaq`009C,r5`009`009; Point to the table of coefficients
X`009pushq`009(r4)
X`009pushl`009#n1
X`009bsbb`009PQEXP_R3`009; X`094n1
X`009pushq`009(r4)
X`009pushl`009#n0-n1
X`009bsbb`009PQEXP_R3
X`009pushq`009(r5)+`009`009; C1
X`009bsbw`009PQADD_R0`009; X`094(n0 - n1) + C1
X`009bsbw`009PQMUL_R2`009; X`094n0 + X`094n1*C1
X`009pushq`009(r5)+`009`009; C2
X`009pushq`009(r4)
X`009bsbw`009PQMUL_R2`009; X*C2
X`009pushq`009(r5)+`009`009; C3
X`009bsbw`009PQADD_R0`009; X*C2 + C3
X`009pushq`009(r4)
X`009bsbb`009PQMUL_R2`009; X`0942*C2 + X*C3
X`009pushq`009(r5)+`009`009; C4
X`009bsbw`009PQADD_R0`009; X`0942*C2 + X*C3 + C4
X`009pushq`009(r4)
X`009bsbb`009PQMUL_R2`009; X`0943*C2 + X`0942*C3 + C4*X
X`009pushq`009(r5)+`009`009; C5
X`009bsbw`009PQADD_R0`009; X`0943*C2 + X`0942*C3 + C4*X + C5
X`009bsbw`009PQADD_R0`009; Add in the high order terms
X`009popq`009@4(ap)`009`009; Replace U with f(X)
X`009movl`009#1,r0
X`009ret
X`032
X`032
XPQEXP_R3:
X.enabl`009LSB
V; Replaces the inputs with U`094n mod P where P is of the form P = 2`09464 -
X a.
X; U is a quadword, n is an unsigned longword.
X`032
X`009popr`009#`094M<r3>`009`009; Record return address
X`009pushq`009#1`009`009; Initialize
X`009pushq`0098+4(sp)`009`009; Copy U to top of stack for speed
X`009tstl`0098+8(sp)`009`009; Only handle n greater than 0
X`009beqlu`00930$
X10$:`009blbc`0098+8(sp),20$
X`009pushq`009(sp)`009`009; Copy the current power of U
X`009pushq`0098+8(sp)`009`009; Multiply with current value
X`009bsbb`009PQMUL_R2
X`009popq`0098(sp)`009`009; Replace current value
X`009cmpzv`009#1,#31,8+8(sp),#0
X`009beqlu`00930$
X20$:`009pushq`009(sp)`009`009; Proceed to next power of U
X`009bsbb`009PQMUL_R2
X`009extzv`009#1,#31,8+8(sp),8+8(sp)
X`009brb`00910$
X30$:`009movq`0098(sp),8+8+4(sp)`009; Copy the return value
X`009movaq`0098+8+4(sp),sp`009; Discard the exponent
X`009jmp`009(r3)`009`009; return
X.dsabl`009LSB
X`032
Xu=0`009`009`009`009; Low longword of U
Xv=u+4`009`009`009`009; High longword of U
Xy=u+8`009`009`009`009; Low longword of Y
Xz=y+4`009`009`009`009; High longword of Y
X`032
XPQMOD_R0:
X.enabl`009LSB
X; Replaces the quadword U on the stack with U mod P where P is of the
X; form P = 2`09464 - a.
X`032
X`009popr`009#`094M<r0>`009`009; Record return address
X`009cmpl`009v(sp),#-1`009; Replace U with U mod P
X`009blssu`00910$
X`009cmpl`009u(sp),#-a
X`009blssu`00910$
X`009addl2`009#a,u(sp)
X`009adwc`009#0,v(sp)
X10$:`009jmp`009(r0)`009`009; return
X.dsabl`009LSB
X`032
X`032
XPQMUL_R2:
X; Computes the product U*Y mod P where P is of the form P = 2`09464 - a.
X; U, Y are quadwords less than P.  The product replaces U and Y on the stack.
X`032
X; The product may be formed as the sum of four longword multiplications
X; which are scaled by powers of 2`09432 by evaluating:
X; 2`09464*v*z + 2`09432*(v*y + u*z) + u*y
X; The result is computed such that division by the modulus P is avoided.
X`032
X`009popr`009#`094M<r1>`009`009; Record return address
X`009movl`009sp,r2`009`009; Record initial stack value
X`009pushl`009z(r2)
X`009pushl`009v(r2)
X`009bsbb`009EMULQ
X`009bsbb`009PQMOD_R0
X`009bsbb`009PQLSH_R0`009; Obtain 2`09432*v*z
X`009pushl`009y(r2)
X`009pushl`009v(r2)
X`009bsbb`009EMULQ
X`009bsbb`009PQMOD_R0
X`009pushl`009z(r2)
X`009pushl`009u(r2)
X`009bsbb`009EMULQ
X`009bsbb`009PQMOD_R0
X`009bsbb`009PQADD_R0`009; Obtain (v*y + u*z)
X`009bsbb`009PQADD_R0`009; Add in 2`09432*v*z
X`009bsbb`009PQLSH_R0`009; Obtain the first two terms
X`009pushl`009y(r2)
X`009pushl`009u(r2)
X`009bsbb`009EMULQ
X`009bsbb`009PQMOD_R0`009; Obtain the third term:  u*y
X`009bsbb`009PQADD_R0`009; Add it in
X`009popq`009Y(r2)`009`009; Copy the return value
X`009movaq`009Y(r2),sp`009; Point the stack to the return value
X`009jmp`009(r1)`009`009; return
X`032
X`032
XEMULQ:
X.enabl`009LSB
X; This routine knows how to multiply two unsigned longwords, replacing them
X; with the unsigned quadword product on the stack.
X`032
X`009emul`0094(sp),8(sp),#0,-(sp)
X`009clrl`009-(sp)
X`009tstl`0094+8+4(sp)`009; Check both longwords to see if we must
X`009bgeq`00910$`009`009; compensate for the unsigned bias.
X`009addl`0094+8+8(sp),(sp)
X10$:`009tstl`0094+8+8(sp)
X`009bgeq`00920$
X`009addl`0094+8+4(sp),(sp)
X20$:`009addl`009(sp)+,4(sp)`009; Add in the compensation.
X`009popq`0094(sp)`009`009; Replace the longwords with their product.
X`009rsb
X.dsabl`009LSB
X`032
X`032
XPQLSH_R0:
X.enabl`009LSB
V; Computes the product 2`09432*U mod P where P is of the form P = 2`09464 - a
X.
X; U is a quadword less than P.  The product replaces U on the stack.
X`032
X; This routine is used by PQMUL in the formation of quadword products in
X; such a way as to avoid division by the modulus P.
V; The product 2`09464*v + 2`09432*u is congruent a*v + 2`09432*u mod P (where
X u, v
X; are longwords).
X`032
X`009popr`009#`094M<r0>`009`009; Record return address
X`009pushl`009v(sp)
X`009pushl`009#a
X`009bsbb`009EMULQ`009`009; Push a*v
X`009ashq`009#32,Y(sp),Y(sp)`009; Form Y = 2`09432*u
X`009brb`00910$`009`009; Return the sum U + Y mod P.
X`032
XPQADD_R0:
X; Computes the sum U + Y mod P where P is of the form P = 2`09464 - a.
X; U, Y are quadwords less than P.  The sum replaces U and Y on the stack.
X`032
X`009popr`009#`094M<r0>`009`009; Record return address
X10$:`009addl2`009u(sp),y(sp)`009; Add the low longwords
X`009adwc`009v(sp),z(sp)`009; Add the high longwords with the carry
X`009bcs`00920$`009`009; If the result is greater than a quadword
X`009cmpl`009z(sp),#-1
X`009blssu`00930$
X`009cmpl`009y(sp),#-a`009; or simply greater than or equal to P
X`009blssu`00930$
X20$:`009addl2`009#a,y(sp)`009; we must subtract P.
X`009adwc`009#0,z(sp)
X30$:`009movaq`009Y(sp),sp`009; Point the stack to the return value
X`009jmp`009(r0)`009`009; return
X.dsabl`009LSB
X`032
X.END
$ GOSUB UNPACK_FILE

$ FILE_IS = "INIT_CLI.C"
$ CHECKSUM_IS = 123436198
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X#include <descrip.h>
X`032
X/* "table" is a pointer to the internal CLD
X * "name" is a text string containing the name of the verb
X */
Xint init_cli(table, name)
Xint (*table)();
Xchar *name;
X`123
X  static struct dsc$descriptor cmd = `1230,DSC$K_DTYPE_T,DSC$K_CLASS_D,0`125;
X  static $DESCRIPTOR(verb,"$VERB");
X  static $DESCRIPTOR(line,"$LINE");
X  int i,sts;
X`032
X  sts = CLI$GET_VALUE(&verb,&cmd);
X  if (!(sts & 1)) return(sts);
X
X  if (strncmp(cmd.dsc$a_pointer,name,cmd.dsc$w_length) == 0)
X  `123
X    return(1);    /* the command must have been properly defined! */
X  `125
X  else
X  `123
X    /* this code assumes that the verb is shorter than than the foreign
X       symbol (which includes device:[dir], so, should be reasonable) */
X    sts = CLI$GET_VALUE(&line,&cmd);
X    if (!(sts & 1)) return(sts);
X
X    for (i = 0; (i < cmd.dsc$w_length) &&
X                (cmd.dsc$a_pointer[i] != ' ') &&
X                (cmd.dsc$a_pointer[i] != '/'); ++i)
X      cmd.dsc$a_pointer[i] = (i < strlen(name))?name[i]:' ';
X
X    return(CLI$DCL_PARSE(&cmd,*table)); /* initialize the parse tables */
X  `125
X`125
$ GOSUB UNPACK_FILE

$ FILE_IS = "MAKEFILE."
$ CHECKSUM_IS = 554591140
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
XCC =
XLINK =
XUAF = uaf select display parse parse_uic init_cli uafcld hpwd
X
X# choose one of the following
XCOMPILER = CC
X# COMPILER = GCC
X
Xall : uaf.hlp uaf.exe guess_password.exe
X
Xuaf.hlp : $*.rnh
X`009runoff $*.rnh
X
Xuaf.exe : $(UAF).obj
X`009link/notrace$(LINK) $(UAF), $(COMPILER)/opt
X
Xguess_password.exe : $*.obj hpwd.obj
X`009link/notrace$(LINK) $?, $(COMPILER)/opt
X
Xuafcld.obj : $*.cld
X`009set command/object $*
X
Xparse_uic.obj : $*.mar
X`009macro $*
X
Xguess_password.obj : $*.c wordlist.h
X
Xhpwd.obj : $*.mar
X`009macro $*
X
X.c.obj :
X`009$(COMPILER)$(CC) $*
$ GOSUB UNPACK_FILE

$ FILE_IS = "PARSE.C"
$ CHECKSUM_IS = 68771580
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X#include <ctype.h>
X#include <string.h>
X
X#include <climsgdef.h>
X#include <descrip.h>
X
X#include "uaf.h"
X#include "uaf_cld.h"
X
X#define MIN(a,b) ((a)<(b))?(a):(b)
X#define SWAP(a,b) `123(a) `094= (b); (b) `094= (a); (a) `094= (b);`125
X
Vstatic struct dsc$descriptor prefix = `1230,DSC$K_DTYPE_T,DSC$K_CLASS_D,0`125
X;
Xstatic struct dsc$descriptor item = `1230,DSC$K_DTYPE_T,DSC$K_CLASS_D,0`125;
X
Xinit_parse(char *s1)
X`123
X  struct dsc$descriptor d1 = `123s1?strlen(s1):0,0,0,s1`125;
X
X  str$copy_dx(&prefix,&d1);
X`125
X
Xadd_parse(char *s1)
X`123
X  struct dsc$descriptor d1 = `123s1?strlen(s1):0,0,0,s1`125;
X
X  str$append(&prefix,&d1);
X`125
X
Xcli_present(char *s1)
X`123
X  struct dsc$descriptor d1 = `123s1?strlen(s1):0,0,0,s1`125;
X  str$copy_dx(&item,&prefix);
X  str$append(&item,&d1);
X  return(cli$present(&item));
X`125
X
Xpresent(char *s1)
X`123
X  struct dsc$descriptor d1 = `123s1?strlen(s1):0,0,0,s1`125;
X
X  str$copy_dx(&item,&prefix);
X  str$append(&item,&d1);
X
X  return(cli$present(&item) & 1);
X`125
X
Xvoid *get_value(char *s1)
X`123
X  struct dsc$descriptor d2 = `1230,DSC$K_DTYPE_T,DSC$K_CLASS_D,0`125;
X  struct dsc$descriptor null = `1231,DSC$K_DTYPE_T,DSC$K_CLASS_D,"\0"`125;
X  int sts;
X
X  if (present(s1))
X  `123
X    sts = cli$get_value(&item,&d2);
X    if (sts & 1)
X    `123
X      str$append(&d2,&null);
X      return(d2.dsc$a_pointer);
X    `125
X  `125
X  return( (void *)0);
X`125
X
Xparse_byte(char *s1, char *min, char *max)
X`123
X  char *s2;
X  if (s2 = get_value(s1))
X  `123
X    *min = atoi(s2);
X    if (s2 = get_value(s1))
X      *max = atoi(s2);
X    else
X      *max = 0x7f;
X    if (*max < *min) SWAP(*min,*max);
X    return(1);
X  `125
X  return(0);
X`125
X
Xparse_word(char *s1, short *min, short *max)
X`123
X  char *s2;
X  if (s2 = get_value(s1))
X  `123
X    *min = atoi(s2);
X    if (s2 = get_value(s1))
X      *max = atoi(s2);
X    else
X      *max = 0x7fff;
X    if (*max < *min) SWAP(*min,*max);
X    return(1);
X  `125
X  return(0);
X`125
X
Xparse_long(char *s1, long *min, long *max)
X`123
X  char *s2;
X  if (s2 = get_value(s1))
X  `123
X    *min = atoi(s2);
X    if (s2 = get_value(s1))
X      *max = atoi(s2);
X    else
X      *max = 0x7fffffff;
X    if (*max < *min) SWAP(*min,*max);
X    return(1);
X  `125
X  return(0);
X`125
X
Xparse_ctext(char *s1, char *s2, int len)
X`123
X  char *s3;
X  s2[0] = '\0';
X  if (s3 = get_value(s1))
X  `123
X    s2[0] = MIN(strlen(s3)+1,len);
X    strncpy(&s2[1],s3,s2[0]);
X    strnupcase(&s2[1],s2[0]);
X    return(1);
X  `125
X  return(0);
X`125
X
Xparse_text(char *s1, char *s2, int len)
X`123
X  char *s3;
X  int s3len;
X  s2[0] = '\0';
X  if (s3 = get_value(s1))
X  `123
X    s3len = MIN(strlen(s3)+1,len); /* try to copy trailing null if room */
X    strncpy(s2,s3,s3len);
X    strnupcase(s2,s3len);
X    return(1);
X  `125
X  return(0);
X`125
X
Xstrnupcase(char *s, int len)
X`123
X  while (len)
X  `123
X    if (islower(*s)) *s = toupper(*s);
X    ++s; --len;
X  `125
X`125
X
Xparse_password(char *s1, char *s2, char *s3, int len)
X`123
X  char *s4;
X  s2[0] = '\0';
X  s3[0] = '\0';
X  if (s4 = get_value(s1))
X  `123
X    s2[0] = MIN(strlen(s4),len);
X    strncpy(&s2[1],s4,s2[0]);
X    strnupcase(&s2[1],s2[0]);
X
X    if (s4 = get_value(s1))
X    `123
X      s3[0] = MIN(strlen(s4),len);
X      strncpy(&s3[1],s4,s3[0]);
X      strnupcase(&s3[1],s3[0]);
X    `125                 `032
X    return(1);
X  `125                 `032
X  return(0);
X`125
X
Xparse_privileges(char *s1, union prvdef *set, union prvdef *clr)
X`123
X  long sts, i;
X
X  if (!present(s1)) return(0);
X  add_parse(s1); add_parse(".");
X
X  if (present("CLASS"))
X  `123 /* parse CLASS= */
X    add_parse("CLASS"); add_parse(".");
X
X    if ((sts = cli_present("ALL")) & 1)
X    `123
V      set->prv$q_privilege[0] `124= PRV$M_BYPASS `124 PRV$M_CMEXEC `124 PRV$M
X_CMKRNL
X`009`124 PRV$M_DETACH `124 PRV$M_LOG_IO `124 PRV$M_PFNMAP `124 PRV$M_PHY_IO
X`009`124 PRV$M_SETPRV `124 PRV$M_SHARE `124 PRV$M_SYSNAM `124 PRV$M_SYSPRV;
X      set->prv$q_privilege[1] `124= PRV$M_READALL;
X    `125
X    else if (sts == CLI$_NEGATED)
X    `123
V      clr->prv$q_privilege[0] `124= PRV$M_BYPASS `124 PRV$M_CMEXEC `124 PRV$M
X_CMKRNL
X`009`124 PRV$M_DETACH `124 PRV$M_LOG_IO `124 PRV$M_PFNMAP `124 PRV$M_PHY_IO
X`009`124 PRV$M_SETPRV `124 PRV$M_SHARE `124 PRV$M_SYSNAM `124 PRV$M_SYSPRV;
X      clr->prv$q_privilege[1] `124= PRV$M_READALL;
X    `125
X
X    if ((sts = cli_present("FILES")) & 1)
X    `123
X      set->prv$q_privilege[0] `124= PRV$M_DIAGNOSE `124 PRV$M_SYSGBL
X`009`124 PRV$M_VOLPRO;
X      set->prv$q_privilege[1] `124= PRV$M_UPGRADE
X`009`124 PRV$M_DOWNGRADE `124 PRV$M_SECURITY;
X    `125
X    else if (sts == CLI$_NEGATED)
X    `123
X      clr->prv$q_privilege[0] `124= PRV$M_DIAGNOSE `124 PRV$M_SYSGBL
X`009`124 PRV$M_VOLPRO;
X      clr->prv$q_privilege[1] `124= PRV$M_UPGRADE
X`009`124 PRV$M_DOWNGRADE `124 PRV$M_SECURITY;
X    `125
X
X    if ((sts = cli_present("SYSTEM")) & 1)
X      set->prv$q_privilege[0] `124= PRV$M_ALTPRI `124 PRV$M_OPER
X`009`124 PRV$M_PSWAPM `124 PRV$M_WORLD;
X    else if (sts == CLI$_NEGATED)
X      clr->prv$q_privilege[0] `124= PRV$M_ALTPRI `124 PRV$M_OPER
X`009`124 PRV$M_PSWAPM `124 PRV$M_WORLD;
X
X    if ((sts = cli_present("DEVOUR")) & 1)
V      set->prv$q_privilege[0] `124= PRV$M_ACNT `124 PRV$M_ALLSPOOL `124 PRV$M
X_BUGCHK
X`009`124 PRV$M_EXQUOTA `124 PRV$M_GRPNAM `124 PRV$M_PRMCEB `124 PRV$M_PRMGBL
X`009`124 PRV$M_PRMMBX `124 PRV$M_SHMEM `124 PRV$M_SYSLCK;
X    else if (sts == CLI$_NEGATED)
V      set->prv$q_privilege[0] `124= PRV$M_ACNT `124 PRV$M_ALLSPOOL `124 PRV$M
X_BUGCHK
X`009`124 PRV$M_EXQUOTA `124 PRV$M_GRPNAM `124 PRV$M_PRMCEB `124 PRV$M_PRMGBL
X`009`124 PRV$M_PRMMBX `124 PRV$M_SHMEM `124 PRV$M_SYSLCK;
X
X    if ((sts = cli_present("GROUP")) & 1)
X    `123
X      set->prv$q_privilege[0] `124= PRV$M_GROUP;
X      set->prv$q_privilege[1] `124= PRV$M_GRPPRV;
X    `125
X    else if (sts == CLI$_NEGATED)
X    `123
X      clr->prv$q_privilege[0] `124= PRV$M_GROUP;
X      clr->prv$q_privilege[1] `124= PRV$M_GRPPRV;
X    `125
X
X    if ((sts = cli_present("NORMAL")) & 1)
V      set->prv$q_privilege[0] `124= PRV$M_MOUNT `124 PRV$M_NETMBX `124 PRV$M_
XTMPMBX;
X    else if (sts == CLI$_NEGATED)
V      clr->prv$q_privilege[0] `124= PRV$M_MOUNT `124 PRV$M_NETMBX `124 PRV$M_
XTMPMBX;
X
X  `125 /* end of CLASS = parse */
X
X  init_parse("SELECT.");
X  add_parse(s1); add_parse(".");
X
X  for (i = 0; i < 32; ++i)
X  `123
X    if ((sts = cli_present(priv_txt[i])) & 1)
X      set->prv$q_privilege[0] `124= (1 << i);
X    else if (sts == CLI$_NEGATED)
X      clr->prv$q_privilege[0] `124= (1 << i);
X  `125
X  for (i = 0; i < 7; ++i)
X  `123
X    if ((i != 4) && (i != 5)) /* these two have been removed! */
X    `123
X      if ((sts = cli_present(priv_txt[i + 32])) & 1)
X        set->prv$q_privilege[1] `124= (1 << i);
X      else if (sts == CLI$_NEGATED)
X        clr->prv$q_privilege[1] `124= (1 << i);
X    `125
X  `125
X
X  init_parse("SELECT.");
X  return(1);
X`125
X
Xparse_date(char *s1, long min[2], long max[2])
X`123
X  struct dsc$descriptor d2;
X
X  if (d2.dsc$a_pointer = get_value(s1))
X  `123
X    d2.dsc$w_length = strlen(d2.dsc$a_pointer);
X    if (d2.dsc$w_length == 0)
X    `123
X      min[1] = 0x80000000; min[0] = 0x00000000;
X    `125
X    else
X    `123
X      sys$bintim(&d2,min);
X    `125
X    if (d2.dsc$a_pointer = get_value(s1))
X    `123
X      d2.dsc$w_length = strlen(d2.dsc$a_pointer);
X      sys$bintim(&d2,max);
X    `125
X    else
X    `123
X      max[1] = 0x7fffffff; max[0] = 0xffffffff;
X    `125
X    /* which is smaller? put smallest in min */
X    if (max[1] < min[1])
X    `123
X      SWAP(min[1],max[1]); SWAP(min[0],max[0]);
X    `125
X    else
X    `123
X      if ((max[1] == min[1]) && (max[0] < min[0]))
X      `123
X        SWAP(min[1],max[1]); SWAP(min[0],max[0]);
X      `125
X    `125
X    return(1);
X  `125
X  return(0);
X`125
X
Xparse_flags(char *s1, unsigned long *set, unsigned long *clr)
X`123
X  long sts, i;
X
X  if (!present(s1)) return(0);
X  add_parse(s1); add_parse(".");
X
X  for (i = 0; i < 16; ++i)
X  `123
X    if ((sts = cli_present(flag_txt[i])) & 1)
X      *set `124= (1 << i);
X    else if (sts == CLI$_NEGATED)
X      *clr `124= (1 << i);
X  `125
X
X  init_parse("SELECT.");
X  return(1);
X`125
X
Xparse_days(char *s1,
X        /* this is opposite what you may expect, a prime day bit is clear */
X`009char *clr,
X`009char *set)
X`123
X  int sts, i;
X
X  if (!present(s1)) return(0);
X  add_parse(s1); add_parse(".");
X
X  for (i = 0; i < 7; ++i)
X  `123
X    if ((sts = cli_present(primeday_txt[i])) & 1)
X      *set `124= (1 << i);           `032
X    else if (sts == CLI$_NEGATED)
X      *clr `124= (1 << i);
X  `125
X
X  init_parse("SELECT.");
X  return(1);
X`125
X
Xcli_parse_uic(char *s1, long *uic)
X`123
X  int sts;
X  char *s2;
X  struct dsc$descriptor d2 = `1230,0,0,0`125;
X
X  if (s2 = get_value(s1))
X  `123
X    d2.dsc$w_length = strlen(s2);
X    d2.dsc$a_pointer = s2;
X    sts = parse_uic(&d2,uic);
X
X    return(sts & 1);
X  `125
X  return(0);
X`125
X
Xparse_access(char *str1, char *pri1, char *pri2, char *sec1, char *sec2)
X`123
X  char *str2, *dash;
X  long p1 = 0, p2 = 0, s1 = 0, s2 = 0, *t = &p1, hr, hs, hf, parsed = 0;
X
X  if (!present(str1)) return(0);
X
X  while (str2 = get_value(str1))
X  `123
X    parsed = 0;
X
X    if ((hr = hour(str2)) > -1)`009/* is it an hour? */
X    `123 /* this is a number, set the right bit! */
X      *t `124= (1 << hr);
X      parsed = -1;
X    `125
X
X    if (!parsed && (dash = strchr(str2,'-')))
X    `123 /* set a range of hours */
X      *dash = '\0'; ++dash;
X      if ((hs = hour(str2)) == -1)
X      `123 /* oops, not a number, bitch and moan */
X        return(0);
X      `125
X      if ((hf = hour(dash))== -1)
X      `123 /* oops, not a number, bitch and moan */
X        return(0);
X      `125
X      for (hr = hs; hr <= hf; ++hr)
X      `123 /* set the bit for this hour */
X        *t `124= (1 << hr);
X      `125                        `032
X      parsed = -1;
X    `125
X
X    if (!parsed && string_eq(str2,"PRIMARY"))
X    `123
X      t = &p1;
X      parsed = -1;
X    `125
X
X    if (!parsed && string_eq(str2,"NOPRIMARY"))
X    `123
X      t = &p2;
X      parsed = -1;
X    `125
X
X    if (!parsed && string_eq(str2,"SECONDARY"))
X    `123
X      t = &s1;
X      parsed = -1;
X    `125
X
X    if (!parsed && string_eq(str2,"NOSECONDARY"))
X    `123
X      t = &s2;
X      parsed = -1;
X    `125
X
X    if (!parsed)
X    `123 /* hmm, we didn't find anything sensible in that */
X      return(0);
X    `125
X  `125
X
X  memcpy(pri1, &p1, 3);
X  memcpy(pri2, &p2, 3);
X  memcpy(sec1, &s1, 3);
X  memcpy(sec2, &s2, 3);
X
X  return(1);
X`125
X
Xhour(char *s1)
X`123
X  int hr = 0;
X
X  /* ignore spaces, see if this is a number! */
X  while (isspace(*s1)) ++s1;
X
X  while (isdigit(*s1))
X  `123
X    hr = hr * 10 + (*s1 - '0');
X    ++s1;
X  `125
X
X  while (isspace(*s1)) ++s1;
X
X  if (*s1)
X    return(-1);
X  else
X    return(hr);
X`125
X
Xstring_eq(char *s1, char *s2)
X`123
X  int i;
X
X  while (isspace(*s1)) ++s1;
X  for (i = 0; i < strlen(s1); ++i)
X  `123
X    if (islower(s1[i]))
X      s1[i] = toupper(s1[i]);
X  `125
X
X  if (strncmp(s1,s2,strlen(s1)) == 0)
X    return(1);
X  else
X    return(0);
X`125
$ GOSUB UNPACK_FILE

$ FILE_IS = "PARSE_UIC.MAR"
$ CHECKSUM_IS = 1496995982
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X$tpadef
X
Xtparse_init:
X`009.long`009tpa$k_count0
X`009.long`009tpa$m_blanks!tpa$m_abbrev
Xtparse:`009.blkb`009tpa$k_length0
X
X`009$init_state`009uic_stb,uic_ktb
X`009$state
X`009$tran`009tpa$_ident,,,,uic
X`009$state
X`009$tran`009tpa$_eos,tpa$_exit
X`009$end_state
X
Xuic:`009.long
X
X`009.entry`009parse_uic,`094m<r2,r3,r4,r5>
X
X`009; initialize tparse block
X`009movc5`009#8,tparse_init,#0,#tpa$k_length0,tparse
X
X`009; set the tparse block string info
X`009movl`0094(ap),r0
X`009movzwl`009(r0),tparse+tpa$l_stringcnt
X`009movl`0094(r0),tparse+tpa$l_stringptr
X
X`009; call lib$tparse
X`009pushab`009uic_ktb
X`009pushab`009uic_stb
X`009pushab`009tparse
X`009calls`009#3,g`094lib$tparse
X
X`009movl`009uic,@8(ap)
X`009ret
X
X`009.end
$ GOSUB UNPACK_FILE

$ FILE_IS = "SELECT.C"
$ CHECKSUM_IS = 574063060
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X#include <descrip.h>
X#include "uaf.h"
X#include "uaf_cld.h"
X
X#define MIN(a,b) ((a) < (b))?(a):(b)
Xselect(struct UAFDEF *record, int len)
X`123
X  static int init = 0, and = 0;
X  static struct UAF_FIELDS field;
X  static struct UAFDEF minimum, maximum;
X
X#define S_PASSWORD 33
X  static char password1[S_PASSWORD], password2[S_PASSWORD], pswd_bin[8];
X  static struct dsc$descriptor
X    pswd1 = `1230,0,0,&password1[1]`125,
X    pswd2 = `1230,0,0,&password2[1]`125,
X    outpswd = `123sizeof(pswd_bin),0,0,pswd_bin`125,
X    usrname = `1230,0,0,0`125;
X
X  int test, i;
X
X  if (!init)
X  `123
X    init = 1;
X
X    init_parse("SELECT.");
X    if (parse_access("ACCESS",
X`009`009`009minimum.uaf$b_batch_access_p,
X`009`009`009maximum.uaf$b_batch_access_p,
X`009`009`009minimum.uaf$b_batch_access_s,
X`009`009`009maximum.uaf$b_batch_access_s))
X    `123
X      field.network_access = 1;
X      field.local_access = 1;
X      field.dialup_access = 1;
X      field.remote_access = 1;
X      memcpy(minimum.uaf$b_network_access_p,minimum.uaf$b_batch_access_p,6);
X      memcpy(maximum.uaf$b_network_access_p,maximum.uaf$b_batch_access_p,6);
X      memcpy(minimum.uaf$b_local_access_p,minimum.uaf$b_batch_access_p,6);
X      memcpy(maximum.uaf$b_local_access_p,maximum.uaf$b_batch_access_p,6);
X      memcpy(minimum.uaf$b_dialup_access_p,minimum.uaf$b_batch_access_p,6);
X      memcpy(maximum.uaf$b_dialup_access_p,maximum.uaf$b_batch_access_p,6);
X      memcpy(minimum.uaf$b_remote_access_p,minimum.uaf$b_batch_access_p,6);
X      memcpy(maximum.uaf$b_remote_access_p,maximum.uaf$b_batch_access_p,6);
X    `125
X    field.rtype = parse_byte("RTYPE",
X`009`009&minimum.uaf$b_rtype,&maximum.uaf$b_rtype);
X    field.version = parse_byte("VERSION",
X`009`009&minimum.uaf$b_version,&maximum.uaf$b_version);
X    field.usrdatoff = parse_word("USRDATOFF",
X`009`009&minimum.uaf$w_usrdatoff,&maximum.uaf$w_usrdatoff);
X    field.logfails = parse_word("LOGFAILS",
X`009`009&minimum.uaf$w_logfails,&maximum.uaf$w_logfails);
X    field.pwd_date = parse_date("PWDCHANGE",
X`009`009minimum.uaf$q_pwd_date,maximum.uaf$q_pwd_date);
X    field.pwd2_date = parse_date("PWD2CHANGE",
X`009`009minimum.uaf$q_pwd2_date,maximum.uaf$q_pwd2_date);
X    field.lastlogin_i = parse_date("INTERACTIVE",
X`009`009minimum.uaf$q_lastlogin_i,maximum.uaf$q_lastlogin_i);
X    field.lastlogin_n = parse_date("NONINTERACTIVE",
X`009`009minimum.uaf$q_lastlogin_n,maximum.uaf$q_lastlogin_n);
X
X    field.account = parse_text("ACCOUNT",
X`009`009minimum.uaf$t_account,UAF$S_ACCOUNT);
X    field.astlm = parse_word("ASTLM",
X`009`009&minimum.uaf$w_astlm,&maximum.uaf$w_astlm);
X    field.batch_access `124= parse_access("BATCH",
X`009`009minimum.uaf$b_batch_access_p,
X`009`009maximum.uaf$b_batch_access_p,
X`009`009minimum.uaf$b_batch_access_s,
X`009`009maximum.uaf$b_batch_access_s);
X    field.biolm = parse_word("BIOLM",
X`009`009&minimum.uaf$w_biolm,&maximum.uaf$w_biolm);
X    field.bytlm = parse_long("BYTLM",
X`009`009&minimum.uaf$l_bytlm,&maximum.uaf$l_bytlm);
X    field.defcli = parse_ctext("CLI",
X`009`009minimum.uaf$t_defcli,UAF$S_DEFCLI);
X    field.clitables = parse_ctext("CLITABLES",
X`009`009minimum.uaf$t_clitables,UAF$S_CLITABLES);
X    field.def_priv = parse_privileges("DEFPRIVILEGES",
V`009`009minimum.uaf$r_def_priv_overlay.uaf$q_def_priv, maximum.uaf$r_def_priv
X_overlay.uaf$q_def_priv);
X    field.defdev = parse_ctext("DEVICE",
X`009`009minimum.uaf$t_defdev,UAF$S_DEFDEV);
X    field.dialup_access `124= parse_access("DIALUP",
X`009`009minimum.uaf$b_dialup_access_p,
X`009`009maximum.uaf$b_dialup_access_p,
X`009`009minimum.uaf$b_dialup_access_s,
X`009`009maximum.uaf$b_dialup_access_s);
X    field.diolm = parse_word("DIOLM",
X`009`009&minimum.uaf$w_diolm,&maximum.uaf$w_diolm);
X    field.defdir = parse_ctext("DIRECTORY",
X`009`009minimum.uaf$t_defdir,UAF$S_DEFDIR);
X    field.enqlm = parse_word("ENQLM",
X`009`009&minimum.uaf$w_enqlm,&maximum.uaf$w_enqlm);
X    field.expiration = parse_date("EXPIRATION",
X`009`009minimum.uaf$q_expiration,maximum.uaf$q_expiration);
X    field.fillm = parse_word("FILLM",
X`009`009&minimum.uaf$w_fillm,&maximum.uaf$w_fillm);
X    field.flags = parse_flags("FLAGS",
V`009`009&minimum.uaf$r_flags_overlay.uaf$l_flags,&maximum.uaf$r_flags_overlay
X.uaf$l_flags);
X    field.jtquota = parse_long("JTQUOTA",
X`009`009&minimum.uaf$l_jtquota,&maximum.uaf$l_jtquota);
X    field.lgicmd = parse_ctext("LGICMD",
X`009`009minimum.uaf$t_lgicmd,UAF$S_LGICMD);
X    field.local_access `124= parse_access("LOCAL",
X`009`009minimum.uaf$b_local_access_p,
X`009`009maximum.uaf$b_local_access_p,
X`009`009minimum.uaf$b_local_access_s,
X`009`009maximum.uaf$b_local_access_s);
X    field.maxacctjobs = parse_word("MAXACCTJOBS",
X`009`009&minimum.uaf$w_maxacctjobs,&maximum.uaf$w_maxacctjobs);
X    field.maxdetach = parse_word("MAXDETACH",
X`009`009&minimum.uaf$w_maxdetach,&maximum.uaf$w_maxdetach);
X    field.maxjobs = parse_word("MAXJOBS",
X`009`009&minimum.uaf$w_maxjobs,&maximum.uaf$w_maxjobs);
X    field.network_access `124= parse_access("NETWORK",
X`009`009minimum.uaf$b_network_access_p,
X`009`009maximum.uaf$b_network_access_p,
X`009`009minimum.uaf$b_network_access_s,
X`009`009maximum.uaf$b_network_access_s);
X    field.owner = parse_ctext("OWNER",
X`009`009minimum.uaf$t_owner,UAF$S_OWNER);
V    field.password = parse_password("PASSWORD",password1,password2,S_PASSWORD
X);
X    if (field.password)
X    `123
X      pswd1.dsc$w_length = password1[0];
X      pswd2.dsc$w_length = password2[0];
X    `125
X    field.pgflquota = parse_long("PGFLQUOTA",
X`009`009&minimum.uaf$l_pgflquota,&maximum.uaf$l_pgflquota);
X    field.prccnt = parse_word("PRCLM",
X`009`009&minimum.uaf$w_prccnt,&maximum.uaf$w_prccnt);
X    field.primedays = parse_days("PRIMEDAYS",
V`009`009&minimum.uaf$r_primedays_overlay.uaf$b_primedays,&maximum.uaf$r_prime
Xdays_overlay.uaf$b_primedays);
X    field.pri = parse_byte("PRIORITY",
X`009`009&minimum.uaf$b_pri,&maximum.uaf$b_pri);
X    field.priv = parse_privileges("PRIVILEGES",
V`009`009minimum.uaf$r_priv_overlay.uaf$q_priv,maximum.uaf$r_priv_overlay.uaf$
Xq_priv);
X    /* PWDEXPIRED */
X    field.pwd_lifetime = parse_date("PWDLIFETIME",
X`009`009minimum.uaf$q_pwd_lifetime, maximum.uaf$q_pwd_lifetime);
X    field.pwd_length = parse_byte("PWDMINIMUM",
X`009`009&minimum.uaf$b_pwd_length,&maximum.uaf$b_pwd_length);
X    field.remote_access `124= parse_access("REMOTE",
X`009`009minimum.uaf$b_remote_access_p,
X`009`009maximum.uaf$b_remote_access_p,
X`009`009minimum.uaf$b_remote_access_s,
X`009`009maximum.uaf$b_remote_access_s);
X    field.shrfillm = parse_word("SHRFILLM",
X`009`009&minimum.uaf$w_shrfillm,&maximum.uaf$w_shrfillm);
X    field.tqcnt = parse_word("TQELM",
X`009`009&minimum.uaf$w_tqcnt,&maximum.uaf$w_tqcnt);
X    field.uic = cli_parse_uic("UIC",
X`009`009&minimum.uaf$r_uic_overlay.uaf$l_uic);
X    field.username = parse_text("USERNAME",
X`009`009minimum.uaf$t_username,UAF$S_USERNAME);
X    field.dfwscnt = parse_long("WSDEFAULT",
X`009`009&minimum.uaf$l_dfwscnt,&maximum.uaf$l_dfwscnt);
X    field.wsextent = parse_long("WSEXTENT",
X`009`009&minimum.uaf$l_wsextent,&maximum.uaf$l_wsextent);
X    field.wsquota = parse_long("WSQUOTA",
X`009`009&minimum.uaf$l_wsquota,&maximum.uaf$l_wsquota);
X    init_parse("MATCH.");
X    and = present("AND");
X  `125
X
X
X  if (field.rtype)
X  `123
X    test = !((record->uaf$b_rtype < minimum.uaf$b_rtype) `124`124
X`009     (record->uaf$b_rtype > maximum.uaf$b_rtype));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.version)
X  `123
X    test = !((record->uaf$b_version < minimum.uaf$b_version) `124`124
X`009     (record->uaf$b_version > maximum.uaf$b_version));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.usrdatoff)
X  `123
X    test = !((record->uaf$w_usrdatoff < minimum.uaf$w_usrdatoff) `124`124
X`009     (record->uaf$w_usrdatoff > maximum.uaf$w_usrdatoff));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.logfails)
X  `123
X    test = !((record->uaf$w_logfails < minimum.uaf$w_logfails) `124`124
X`009     (record->uaf$w_logfails > maximum.uaf$w_logfails));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.pwd_date)
X  `123
X    test =
V      !((datecmp(record->uaf$q_pwd_date,minimum.uaf$q_pwd_date) == -1) `124`1
X24
X        (datecmp(record->uaf$q_pwd_date,maximum.uaf$q_pwd_date) == 1));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.pwd2_date)
X  `123
X    test =
V      !((datecmp(record->uaf$q_pwd2_date,minimum.uaf$q_pwd2_date) == -1) `124
X`124
X        (datecmp(record->uaf$q_pwd2_date,maximum.uaf$q_pwd2_date) == 1));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.lastlogin_i)
X  `123
X    test =
V      !((datecmp(record->uaf$q_lastlogin_i,minimum.uaf$q_lastlogin_i) == -1)
X `124`124
X        (datecmp(record->uaf$q_lastlogin_i,maximum.uaf$q_lastlogin_i) == 1));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.lastlogin_n)
X  `123
X    test =
V      !((datecmp(record->uaf$q_lastlogin_n,minimum.uaf$q_lastlogin_n) == -1)
X `124`124
X        (datecmp(record->uaf$q_lastlogin_n,maximum.uaf$q_lastlogin_n) == 1));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.account)
X  `123
X    trim(record->uaf$t_account,UAF$S_ACCOUNT);
X
X    test = string_compare(record->uaf$t_account,
X`009`009minimum.uaf$t_account,UAF$S_ACCOUNT + 1);
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.astlm)
X  `123
X    test = !((record->uaf$w_astlm < minimum.uaf$w_astlm) `124`124
X`009     (record->uaf$w_astlm > maximum.uaf$w_astlm));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.batch_access)
X  `123
X    int t1, t2;
X    t1 = check_access(
X`009`009record->uaf$b_batch_access_p,
X`009`009minimum.uaf$b_batch_access_p,
X`009`009maximum.uaf$b_batch_access_p);
X    t2 = check_access(
X`009`009record->uaf$b_batch_access_s,
X`009`009minimum.uaf$b_batch_access_s,
X`009`009maximum.uaf$b_batch_access_s);
X    t1 = t1 && t2;
X    if (t1 && !and) return(1);
X    if (!t1 && and) return(0);
X  `125
X
X  if (field.biolm)
X  `123
X    test = !((record->uaf$w_biolm < minimum.uaf$w_biolm) `124`124
X`009     (record->uaf$w_biolm > maximum.uaf$w_biolm));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.bytlm)
X  `123
X    test = !((record->uaf$l_bytlm < minimum.uaf$l_bytlm) `124`124
X`009     (record->uaf$l_bytlm > maximum.uaf$l_bytlm));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.defcli)
X  `123
X    trim(record->uaf$t_defcli,UAF$S_DEFCLI);
X    test = string_compare(&record->uaf$t_defcli[1] ,
X`009`009&minimum.uaf$t_defcli[1],UAF$S_DEFCLI);
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.clitables)
X  `123
X    trim(record->uaf$t_clitables,UAF$S_CLITABLES);
X    test = string_compare(&record->uaf$t_clitables[1],
X`009`009&minimum.uaf$t_clitables[1],UAF$S_CLITABLES);
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.def_priv)
X  `123 /* minimum.uaf$q_def_priv,maximum.uaf$q_def_priv */
X    test =`032
V      ((minimum.uaf$r_def_priv_overlay.uaf$q_def_priv[0] `124`124 minimum.uaf
X$r_def_priv_overlay.uaf$q_def_priv[1])?
V`009((record->uaf$r_def_priv_overlay.uaf$q_def_priv[0] & minimum.uaf$r_def_pr
Xiv_overlay.uaf$q_def_priv[0]) `124`124
V`009 (record->uaf$r_def_priv_overlay.uaf$q_def_priv[1] & minimum.uaf$r_def_pr
Xiv_overlay.uaf$q_def_priv[1])):1) &&
V      ((maximum.uaf$r_def_priv_overlay.uaf$q_def_priv[0] `124`124 maximum.uaf
X$r_def_priv_overlay.uaf$q_def_priv[1])?
V`009!((record->uaf$r_def_priv_overlay.uaf$q_def_priv[0] & maximum.uaf$r_def_p
Xriv_overlay.uaf$q_def_priv[0]) `124`124
V`009  (record->uaf$r_def_priv_overlay.uaf$q_def_priv[1] & maximum.uaf$r_def_p
Xriv_overlay.uaf$q_def_priv[1])):1);
X
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.defdev)
X  `123
X    trim(record->uaf$t_defdev,UAF$S_DEFDEV);
X    test = string_compare(&record->uaf$t_defdev[1],
X`009`009&minimum.uaf$t_defdev[1],UAF$S_DEFDEV);
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.dialup_access)
X  `123 /* minimum.uaf$b_dialup_access_p,minimum.uaf$b_dialup_access_s); */
X    int t1, t2;
X
X    t1 = check_access(
X`009`009record->uaf$b_dialup_access_p,
X`009`009minimum.uaf$b_dialup_access_p,
X`009`009maximum.uaf$b_dialup_access_p);
X    t2 = check_access(
X`009`009record->uaf$b_dialup_access_s,
X`009`009minimum.uaf$b_dialup_access_s,
X`009`009maximum.uaf$b_dialup_access_s);
X    t1 = t1 && t2;
X    if (t1 && !and) return(1);
X    if (!t1 && and) return(0);
X  `125
X
X  if (field.diolm)
X  `123
X    test = !((record->uaf$w_diolm < minimum.uaf$w_diolm) `124`124
X`009     (record->uaf$w_diolm > maximum.uaf$w_diolm));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.defdir)
X  `123
X    trim(record->uaf$t_defdir,UAF$S_DEFDIR);
X    test = string_compare(&record->uaf$t_defdir[1],
X`009`009&minimum.uaf$t_defdir[1],UAF$S_DEFDIR);
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X     `032
X  if (field.enqlm)
X  `123
X    test = !((record->uaf$w_enqlm < minimum.uaf$w_enqlm) `124`124
X`009     (record->uaf$w_enqlm > maximum.uaf$w_enqlm));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.expiration)
X  `123
X    test =
V      !((datecmp(record->uaf$q_expiration,minimum.uaf$q_expiration) == -1) `1
X24`124
X        (datecmp(record->uaf$q_expiration,maximum.uaf$q_expiration) == 1));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.fillm)
X  `123
X    test = !((record->uaf$w_fillm < minimum.uaf$w_fillm) `124`124
X`009     (record->uaf$w_fillm > maximum.uaf$w_fillm));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.flags)
X  `123
V    test =(minimum.uaf$r_flags_overlay.uaf$l_flags?(record->uaf$r_flags_overl
Xay.uaf$l_flags & minimum.uaf$r_flags_overlay.uaf$l_flags):1)
V      &&  (maximum.uaf$r_flags_overlay.uaf$l_flags?!(record->uaf$r_flags_over
Xlay.uaf$l_flags & maximum.uaf$r_flags_overlay.uaf$l_flags):1);
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.jtquota)
X  `123
X    test = !((record->uaf$l_jtquota < minimum.uaf$l_jtquota) `124`124
X`009     (record->uaf$l_jtquota > maximum.uaf$l_jtquota));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.lgicmd)
X  `123
X    trim(record->uaf$t_lgicmd,UAF$S_LGICMD);
X    test = string_compare(&record->uaf$t_lgicmd[1],
X`009`009&minimum.uaf$t_lgicmd[1],UAF$S_LGICMD);
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.local_access)
X  `123 /* minimum.uaf$b_local_access_p,minimum.uaf$b_local_access_s); */
X    int t1, t2;
X
X    t1 = check_access(
X`009`009record->uaf$b_local_access_p,
X`009`009minimum.uaf$b_local_access_p,
X`009`009maximum.uaf$b_local_access_p);
X    t2 = check_access(
X`009`009record->uaf$b_local_access_s,
X`009`009minimum.uaf$b_local_access_s,
X`009`009maximum.uaf$b_local_access_s);
X    t1 = t1 && t2;
X    if (t1 && !and) return(1);
X    if (!t2 && and) return(0);
X  `125
X
X  if (field.maxacctjobs)
X  `123
X    test = !((record->uaf$w_maxacctjobs < minimum.uaf$w_maxacctjobs) `124`124
X`009     (record->uaf$w_maxacctjobs > maximum.uaf$w_maxacctjobs));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.maxdetach)
X  `123
X    test = !((record->uaf$w_maxdetach < minimum.uaf$w_maxdetach) `124`124
X`009     (record->uaf$w_maxdetach > maximum.uaf$w_maxdetach));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.maxjobs)
X  `123
X    test = !((record->uaf$w_maxjobs < minimum.uaf$w_maxjobs) `124`124
X`009     (record->uaf$w_maxjobs > maximum.uaf$w_maxjobs));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.network_access)
X  `123 /* minimum.uaf$b_network_access_p,minimum.uaf$b_network_access_s); */
X    int t1, t2;
X
X    t1 = check_access(
X`009`009record->uaf$b_network_access_p,
X`009`009minimum.uaf$b_network_access_p,
X`009`009maximum.uaf$b_network_access_p);
X    t2 = check_access(
X`009`009record->uaf$b_network_access_s,
X`009`009minimum.uaf$b_network_access_s,
X`009`009maximum.uaf$b_network_access_s);
X    t1 = t1 && t2;
X    if (t1 && !and) return(1);
X    if (!t1 && and) return(0);
X  `125
X
X  if (field.owner)
X  `123
X    trim(record->uaf$t_owner,UAF$S_OWNER);
X    test = string_compare(&record->uaf$t_owner[1],
X`009`009&minimum.uaf$t_owner[1],UAF$S_OWNER);
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.password)
X  `123
X    usrname.dsc$w_length = 12;
X    usrname.dsc$a_pointer = record->uaf$t_username;
X    outpswd.dsc$w_length = sizeof(pswd_bin);
X    i = lgi$hpwd(&outpswd,&pswd1,record->uaf$b_encrypt,
X`009`009`009record->uaf$w_salt,&usrname);
X    test = cmp_quad(pswd_bin,record->uaf$r_pwd_overlay.uaf$q_pwd);
X    if (test)
X    `123
X      i = lgi$hpwd(&outpswd,&pswd2,record->uaf$b_encrypt2,
X`009`009`009record->uaf$w_salt,&usrname);
X      test = test && cmp_quad(pswd_bin,record->uaf$q_pwd2);
X    `125
X
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.pgflquota)
X  `123
X    test = !((record->uaf$l_pgflquota < minimum.uaf$l_pgflquota) `124`124
X`009     (record->uaf$l_pgflquota > maximum.uaf$l_pgflquota));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.prccnt)
X  `123
X    test = !((record->uaf$w_prccnt < minimum.uaf$w_prccnt) `124`124
X`009     (record->uaf$w_prccnt > maximum.uaf$w_prccnt));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.primedays)
X  `123 /* &minimum.uaf$b_primedays,&maximum.uaf$b_primedays); */
X    test = (minimum.uaf$r_primedays_overlay.uaf$b_primedays?
V`009`009(record->uaf$r_primedays_overlay.uaf$b_primedays & minimum.uaf$r_prim
Xedays_overlay.uaf$b_primedays):1)
X        && (maximum.uaf$r_primedays_overlay.uaf$b_primedays?
V`009`009!(record->uaf$r_primedays_overlay.uaf$b_primedays & maximum.uaf$r_pri
Xmedays_overlay.uaf$b_primedays):1);
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.pri)
X  `123
X    test = !((record->uaf$b_pri < minimum.uaf$b_pri) `124`124
X`009   (  record->uaf$b_pri > maximum.uaf$b_pri));
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  if (field.priv)
V  `123 /* minimum.uaf$r_priv_overlay.uaf$q_priv,maximum.uaf$r_priv_overlay.ua
Xf$q_priv); */
X    test =`032
V      ((minimum.uaf$r_priv_overlay.uaf$q_priv[0] `124`124 minimum.uaf$r_priv_
Xoverlay.uaf$q_priv[1])?
V`009((record->uaf$r_priv_overlay.uaf$q_priv[0] & minimum.uaf$r_priv_overlay.u
Xaf$q_priv[0]) `124`124
V`009 (record->uaf$r_priv_overlay.uaf$q_priv[1] & minimum.uaf$r_priv_overlay.u
Xaf$q_priv[1])):1) &&
V      ((maximum.uaf$r_priv_overlay.uaf$q_priv[0] `124`124 maximum.uaf$r_priv_
Xoverlay.uaf$q_priv[1])?
V`009!((record->uaf$r_priv_overlay.uaf$q_priv[0] & maximum.uaf$r_priv_overlay.
Xuaf$q_priv[0]) `124`124
V`009  (record->uaf$r_priv_overlay.uaf$q_priv[1] & maximum.uaf$r_priv_overlay.
Xuaf$q_priv[1])):1);
X/*
X      (minimum.uaf$r_priv_overlay.uaf$q_priv[0]?
V`009(record->uaf$r_priv_overlay.uaf$q_priv[0] & minimum.uaf$r_priv_overlay.ua
Xf$q_priv[0]):1) &&
X      (minimum.uaf$r_priv_overlay.uaf$q_priv[1]?
V`009(record->uaf$r_priv_overlay.uaf$q_priv[1] & minimum.uaf$r_priv_overlay.ua
Xf$q_priv[1]):1) &&
X      (maximum.uaf$r_priv_overlay.uaf$q_priv[0]?
V`009!(record->uaf$r_priv_overlay.uaf$q_priv[0] & maximum.uaf$r_priv_overlay.u
Xaf$q_priv[0]):1) &&
X      (maximum.uaf$r_priv_overlay.uaf$q_priv[1]?
V`009!(record->uaf$r_priv_overlay.uaf$q_priv[1] & maximum.uaf$r_priv_overlay.u
Xaf$q_priv[1]):1);
X*/
X    if (test && !and) return(1);
X    if (!test && and) return(0);
X  `125
X
X  /* PWDEXPIRED */
X
X  if (field.pwd_lifetime)
X  `123 /* minimum.uaf$q_pwd_lifetime, maximum.uaf$q_pwd_lifetime); */
X    test =
V      !((datecmp(record->uaf$q_pwd_lifetime,minimum.uaf$q_pwd_lifetime) == -1
X)
X       `124`124
V        (datecmp(record->uaf$q_pwd_lifetime,maximum.uaf$q_pwd_lifetime) == 1)
X);
X    if (test && !and) return(1);
-+-+-+-+-+ End of part 2 +-+-+-+-+-
