Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

561 lines
16 KiB

/*
(cv) Copyright (C) Microsoft Corporation, 1983, 1986
*
* This Module contains Proprietary Information of Microsoft
* Corporation and AT&T, and should be treated as Confidential.
*
*
* verify.c - part of zm, code grabbed from ascan.c and atolx.c in mail
*
* Verify a given user alias.
*
* Revision 1.1 85/08/05 18:25:58 vich
* Initial revision (ascan.c version)
*
* Revision 2.0 86/07/22 13:37:19 thomasw
* Revised for zm program and MS-DOS, some procedures were renamed
*
* 09-Apr-1987 mz Use whiteskip/whitescan
*
* 28-Apr-1987 danl VerifyAlias - check for afn
* OpenAlias - CloseAlias on ERROR
* 07-Mar-88 danl Get tools.h from <> not ""
*
*/
#define INCL_DOSINFOSEG
#include "wzport.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <fcntl.h>
#include <share.h>
#include <tools.h>
#include "dh.h"
#include "zm.h"
#define isblank(c) ((c) == ' ' || (c) == '\t')
#define HASHMAGIC "#<hash>\n" /* indicates hashed */
#define HBSIZE 30 /* enough for ptrsize nbuckets hashsize datapos */
/* alias token types: */
#define AT_EOF 1 /* EOF */
#define AT_COMMENT 2 /* #... style comment */
#define AT_STR 3 /* a string */
#define AT_QSTR 4 /* a string that WAS quoted */
#define AT_COLON 5 /* a colon */
#define AT_COMMA 6 /* a comma */
#define AT_NL 7 /* a new line */
#define AT_ALIAS 8 /* beginning of an alias */
#define ATSIZE 100 /* max alias token size */
FILE *afp = NULL; /* current alias file pointer */
FILE *hfp = NULL; /* current hash file pointer */
PSTR afn = NULL; /* current alias file name */
CHAR abuf[ATSIZE + 1]; /* alias buffer (current token) */
LONG apos; /* seek pos to start of current token */
INT atok; /* alias token type */
INT nexttok; /* next token type */
INT lastc; /* last fgetc(afp) */
INT cont; /* 0 if next string token begins a new alias */
LONG nslots; /* # of slots */
LONG hashsize; /* total # of hash table pointers */
LONG hashpos; /* seek address of start of hash table */
LONG datapos; /* seek address of start of data */
INT ptrsize; /* # of bytes per hash table pointer */
INT nbpslot; /* # of buckets per slot */
CHAR ROUTINGCHARS [] = "%!:?@.#";
/* atolx - convert string into long
*
* was:
* atolx ( s ) in atolx.c
*
* arguments:
* s pointer to string to convert
*
* return value:
* long equivalent of string pointed to by s
*
*/
LONG atolx(register PSTR s)
{
INT i;
LONG result;
s = whiteskip (s);
for (result = 0L; isxdigit(*s); s++) {
if ((i = (*s - '0')) > 9) { /* if not 0-9 */
if ((i += '0' - 'A' + 10) > 15) { /* if not A-F */
i += 'A' - 'a'; /* then a-f */
}
}
result = (result * 16) + i;
}
return(result);
}
/* CloseAlias - close the currently open alias file
*
* was:
* endalias ( ) in ascan.c
*
* arguments:
* none
*
* return value:
* none
*
*/
VOID CloseAlias (VOID)
{
if (afp != NULL) {
fclose(afp);
afp = NULL;
}
if (hfp != NULL) {
fclose(hfp);
hfp = NULL;
}
afn = NULL;
return;
}
/* aseek - seek a position in alias file
*
* arguments:
* pos position to seek (same format as arguement for fseek)
*
* return value:
* OK (0) seek successful.
* ERROR (-1) seek unsuccessful.
*
*/
INT aseek (LONG pos)
{
INT c;
if (pos < datapos) {
pos = datapos;
}
if (fseek(afp, pos, 0)) {
return ERROR;
}
cont = 0; /* not a continuation */
do {
c = fgetc(afp);
} while (isblank(c));
if (c == EOF) {
return ERROR;
}
lastc = c;
nexttok = toktype(c, AT_NL, cont); /* set next token type */
return OK;
}
/* OpenAlias - open alias file, and initialize the global variables. MS-DOS
* versions of alias files are found in the $ENVVAR directory or
* at the root level of the current directory
*
* was:
* setalias ( fn ) in ascan.c
*
* arguments:
* fn pointer to file name
*
* return value:
* OK (0) no problemos
* ERROR (-1) error or file is not a hash file
*
*/
INT OpenAlias (PSTR fn)
{
PSTR cp = NULL;
CHAR hashbuf [ HBSIZE + 2 ];
INT hhfp, hafp;
CloseAlias ( );
//instead of:
// hfp = fopen ( fn, "rb" );
// afp = fopen ( fn, "rb" );
// open with sharing, as deny write
if ((hhfp = _sopen(fn, O_RDONLY | O_BINARY, SH_DENYWR, S_IREAD)) == -1)
return ERROR;
if ((hafp = _sopen(fn, O_RDONLY | O_BINARY, SH_DENYWR, S_IREAD)) == -1) {
close(hhfp);
return ERROR;
}
hfp = fdopen ( hhfp, "rb" );
afp = fdopen ( hafp, "rb" );
if ( ( hfp == NULL ) || ( afp == NULL ) ||
fgets(hashbuf, HBSIZE, hfp) == NULL || strcmp(HASHMAGIC, hashbuf))
{
CloseAlias ( );
return ERROR;
}
/* hashed file! */
ptrsize = nbpslot = 0;
hashsize = datapos = 0L;
if (fgets(hashbuf, HBSIZE, hfp) != NULL)
{
cp = whiteskip ( hashbuf );
ptrsize = ( INT ) atolx ( cp );
cp = whitescan ( cp );
cp = whiteskip ( cp );
if ( cp != NULL)
{
nbpslot = ( INT ) atolx ( cp );
cp = whitescan ( cp );
cp = whiteskip ( cp );
if ( cp != NULL)
{
hashsize = atolx ( cp );
cp = whitescan ( cp );
cp = whiteskip ( cp );
if ( cp != NULL)
datapos = atolx ( cp );
}
}
hashpos = ftell(hfp);
nslots = hashsize / nbpslot;
if (ptrsize < 2 || ptrsize > 9 || nbpslot < 1 || nbpslot > 9 ||
hashsize < 1 || datapos != (ptrsize * nslots * nbpslot + hashpos))
{
CloseAlias ( );
return ERROR;
}
}
/* seek start of data */
if (aseek(0L) < 0)
{
CloseAlias ( );
return ERROR;
}
afn = fn;
return OK;
}
/* toktype - given the first character of the next token and the previous
* token's type, return the next token type. Once in a comment, every
* token looks like a comment until a newline is reached. Normal
* strings are AT_ALIAS if this token is not a continuation.
*/
INT toktype (INT c, INT prevtok, INT iscont)
{
if (c != EOF && c != '\n' && prevtok == AT_COMMENT) {
return(AT_COMMENT);
}
switch (c) {
case '"': return(AT_QSTR);
case ':': return(AT_COLON);
case ',': return(AT_COMMA);
case '\n': return(AT_NL);
case EOF: return(AT_EOF);
case '#': if (prevtok == AT_NL) {
return(AT_COMMENT);
}
/* else FALLTHROUGH */
default: return(iscont? AT_STR : AT_ALIAS);
}
}
/* readtok - read a token from the alias file. Store the current token
* type in `atok', the next token type in `nexttok' and the actual
* string in `abuf'. Also store the seek position of the start of
* the token in `apos'. Lines starting with '#' are comments, tokens
* quoted with '"' are allowed any embedded characters except '\n'.
* Other tokens are delimited by blanks, tabs, colons and commas.
*
* A colon is treated as a delimeter ONLY when it follows the first
* string in an alias, as the first colon in foo:mach1:foo,mach2:bar.
* The token type is AT_QSTR only if the string starts out quoted.
* example:
* phonelist:"| cat > /phonelist", kermit:"| cat > /phonelist",
* # comment line...
* robin:supervisor, sysinfo
* parses to: atok abuf
* AT_ALIAS phonelist
* AT_COLON :
* AT_QSTR | cat > /phonelist
* AT_COMMA ,
* AT_STR kermit:| cat > /phonelist
* AT_COMMA ,
* AT_NL \n
* AT_COMMENT #
* AT_COMMENT comment
* AT_COMMENT line...
* AT_NL \n
* AT_STR robin:supervisor
* AT_COMMA ,
* AT_STR sysinfo
* AT_NL \n
* AT_EOF \0
*/
INT readtok (VOID)
{
PSTR cp = NULL;
INT quoted;
INT c;
c = lastc;
atok = nexttok;
apos = ftell(afp) - 1;
for (quoted = 0, cp = abuf; c != EOF; c = fgetc(afp)) {
if (c == '"') {
quoted = !quoted;
continue;
}
if (c == '\n' || (!quoted && strchr(" \t:,", c))) {
if (cp == abuf) {
*cp++ = (CHAR) c;
c = 0;
break;
}
if (!cont || c != ':') {
break;
}
}
if (cp - abuf < ATSIZE - 1) {
*cp++ = (CHAR) c;
}
}
*cp = '\0';
while (c == 0 || isblank(c)) {
c = fgetc(afp);
}
lastc = c;
cont = (atok == AT_COMMA) || (atok == AT_COLON && c != '\n') ||
(cont && (atok == AT_NL || atok == AT_COMMENT));
nexttok = toktype(c, atok, cont);
return(atok != AT_EOF);
}
/* readalias - read alias tokens until the start of a new alias or EOF.
* Return a pointer to the next token. Return NULL if EOF reached.
*/
PSTR readalias (VOID)
{
while (readtok()) {
if (atok == AT_ALIAS) {
return(abuf);
}
}
return((PSTR ) NULL);
}
/* shash - hash the passed string into the given table size.
*
* arguments:
* s pointer to string to hash
* n number of slots in hash table
* nbps number of buckets per slot
*
* return value:
* hashed equivalent of the string pointed to by s
*
*/
LONG shash (PSTR s, LONG n, INT nbps)
{
INT c;
LONG hashval = 0L;
while (c = *s++) {
hashval = (hashval << 1) + tolower(c);
}
return(nbps * ((hashval & 0x7fffffffL) % n));
}
/* schecksum - return a checksum in the range of printable ascii characters;
* (0x20 to 0x7e, ' ' to '~').
*
*/
INT schecksum (PSTR s)
{
INT c;
INT checksum = 0;
while (c = *s++) {
checksum += tolower(c);
}
return((checksum & 0x7fff) % (0x7f - 0x20) + 0x20);
}
/* VerifyAlias - verify that a given alias is in the alias list.
*
* was :
* slookup ( cp ) in ascan.c
*
* arguments:
* cp pointer to user alias to verify
*
* return value:
* OK (0) alias is in the alias file
* ERROR (-1) alias was not found
*
* IMPORTANT:
* alias file MUST have been previously opened with OpenAlias ( ).
*
*/
INT VerifyAlias ( PSTR cp )
{
LONG i;
LONG initial;
LONG dpos;
PSTR key = NULL;
CHAR hbuf[30]; /* enough for one table entry */
INT checksum;
if ( *strbscan ( cp, ROUTINGCHARS ) )
return OK;
if ( !afn )
return ERROR;
initial = i = shash(cp, nslots, nbpslot);
checksum = schecksum(cp);
for ( ; ; ) {
if ((i == 0 || i == initial) &&
fseek(hfp, hashpos + i * ptrsize, 0) < 0) {
return ERROR;
}
if (fread(hbuf, ptrsize, sizeof(CHAR), hfp) != 1 ||
(dpos = atolx(&hbuf[1])) == 0L) {
return ERROR;
}
if ((INT) hbuf[0] == checksum) {
if (aseek(dpos+datapos) < 0 || (key=readalias())==NULL){
return ERROR;
}
if (_strcmpi(cp, key) == 0)
{
dpos = apos;
/* alias found, check to see if it is valid */
while ( ( atok != AT_QSTR ) && ( atok != AT_NL ) )
readtok ( );
if ( atok == AT_QSTR )
{
fseek ( afp, apos, 0 );
fgetl ( hbuf, 30, afp );
key = strbscan ( hbuf, "$" );
/* is the string an error message? */
if ( *( key + 1 ) == 'e' )
return ERROR;
}
aseek ( dpos );
return OK;
}
}
if (++i == hashsize) {
i = 0;
}
if (i == initial) {
return ERROR;
}
}
}
/*
* nextalias - read alias tokens to get next alias string. Return a
* pointer to the next token. Return NULL if we reach EOF or end
* of current alias.
*/
PSTR nextalias (VOID)
{
register INT comma = 0;
while (readtok()) {
switch (atok) {
case AT_STR:
case AT_QSTR:
return(abuf);
case AT_COMMA:
comma++;
break;
case AT_NL:
if (!comma) {
return((PSTR ) NULL); /* end of alias */
}
break;
}
}
return((PSTR ) NULL); /* EOF */
}
PSTR realname ( PSTR pName )
{
register PSTR cp = NULL;
register INT c;
PSTR p = NULL;
if ( !pName || !*pName || VerifyAlias ( pName ) == ERROR )
return NULL;
while (cp = nextalias()) {
if (*cp != '#' && *cp != '$')
goto cont;
if (*cp == '#') {
c = 'e'; /* indicates error */
} else if ((c = *++cp) == '\0') {
continue;
}
cp = whiteskip (cp+1);
switch (c) {
case 'r': /* restricted alias */
goto cont; /* invalid */
case 'e': /* error */
*--cp = '#';
/* FALLTHROUGH*/
case 'n': /* error or real name */
p = ZMMakeStr ( cp );
break;
}
}
cont: ;
return p;
}