

/*======================================================================*/
/*	PSWD	- password table drivers				*/
/*======================================================================*/
/*	Change History							*/
/*----------------------------------------------------------------------*/
/* 2/16/84 - PWInput changed - test the returned value		   -jjc	*/
/* 2/2/84 - Break into HARDPSWD.O and PSWD.O with switch HARDIO	   -jjc	*/
/* 1/84	  - write originally					   -jjc	*/
/*======================================================================*/
#undef  HARDIO
#undef	OVERLAY
#define	GETONLY
#define NODEBUG

#include "pswd.os"
#include "c:switch.os"

#ifdef HARDIO
#include "hardio.h"
#else
#define	READ	0
#define	WRITE	1
#endif


/*==============================================================
	PSWD.C contains the routines necessary to access and 
	update the Control Area (partition zero) System 
	Password Table (PWT).  This table contains 21 six character
	passwords and 2 one character flags.  Only one of these
	flags is used.  The first password is used to determine 
	if the Control Area has been upgraded to seperated boot
	and is never modified by any of these routines.

	The routines used to manipulate this table are:
	
	AutoPW (set)	-* Set Password Table to Auto Mode	*-
	int	set;
		if (set) then set the auto flag in the PWT
		else clear the auto flag in the PWT.

	ClrPW ()	-* Clears all Passwords in the PWT *-
		sets all password except the seperated boot 
		password to blanks and clears the auto flag.

	int GetPW (level) -* Gets a password and checks against PWT *-
	int	level;
		Gets a password from user and checks it against
		the 'levelth' password in the PWT. returns TRUE if
		passwords match else calls zabort.

	int IsPW (level) -* checks for blank or disabled password *-
	int	level;
		if the 'level'th password is blank or the auto flag 
		is set then there is no password (return FALSE)
		else return TRUE.

	PWInput (p, len) -* get 'len' char password from input *-
		actually in MPBIOS module.
	CHAR	p [6];
	int	len;
		This routine gets a 'len' character password from input.
		It understands about BS, CTL-X, DEL.  The array is NOT
		terminated by a newline, it is blank filled if necessary.
		Normally returns TRUE, but FALSE if CTL-C is typed.

	SetPW (level) -* Sets a password in the PWT *-
	int	level;
		Get a new password from user and updates the 'levelth' 
		password in the PWT to the new value.

	int SepBoot ()	-* Check for update to seperated boot *-
	 	If the control area has been upgraded to seperated
		boot the returns TRUE, else returns FALSE
	
	The static data names used by PSWD are:
	PWT
	PWTable
	PWTreadin
		

  ==============================================================*/





#define	true	1
#define	false	0

#define SECTSIZE	128
#define SEPBOOT		"SB0000"

/*==============================================================*/
/*	Password Table						*/
/*==============================================================*/
#define PWTtrack	0x01
#define	PWTsector	0x17
#define PWTlength	1	/* in sectors	*/

#define PWTMAX	21
#define PWLEN	6
struct PWTentry {
	CHAR	Sys_Password [PWLEN];
	};

struct {
	struct PWTentry	table [PWTMAX];
	CHAR		autoflag;
	CHAR		PWreserved;
	} PWT;

struct PWTentry	*PWTable;

int	PWTreadin = false;

#define	AutoMode()	(PWT.autoflag & 0x01)
#define BlankPW		"      "

#ifdef HARDIO
#define PUTPW(b)	hd_xfer (WRITE, PWTtrack, PWTsector+1, b, PWTlength);
#define GETPW(b)	hd_xfer (READ,  PWTtrack, PWTsector+1, b, PWTlength);
#else
#define PUTPW(b)	data_xfer (WRITE, PWTtrack, PWTsector, b, PWTlength);
#define GETPW(b)	data_xfer (READ,  PWTtrack, PWTsector, b, PWTlength);
#endif

#define EnterAgain	"Please enter the same password again, to verify its correctness.\n"
#define NoGood	"Sorry, the two passwords you typed didn't match, please try again.\n"
#ifdef HARDIO
#define NotMaster	"Sorry, password manipulation not supported on a master\n"
#endif

/*page*/
/*==============================================================*/
/*	getPWT and putPWT	- low level I/O			*/
/*==============================================================*/
putPWT (b) 
struct PWTentry *b;
{
#ifndef NODEBUG
	printf ("\tWrite PWT, from %0x\n", b);
#endif 
	PUTPW (b);
	}

getPWT (b) 
struct PWTentry *b;
{
#ifndef NODEBUG
	printf ("\tRead PWT, stored at %0x\n", b);
#endif
	GETPW (b);
	}

/*page*/
/*==============================================================*/
/*	krypt		- encrypt password			*/
/*==============================================================*/
sw (p1, p2)
CHAR	*p1, *p2;
{
CHAR	t1, t2;
	t1 = *p1 & 0x0F;
	t2 = *p2 & 0x0F;
	*p2 &= 0xF0;
	*p1 &= 0XF0;
	*p1 |= ~(t2 | 0xF0);
	*p2 |= ~(t1 | 0xF0);
	}

krypt (p)
CHAR	*p;
{
	if ((strncmp (p, "      ", 6) == 0)
		|| (strncmp (p, "//////", 6) == 0)) return;
	sw (p, p+5);
	sw (p+1, p+4);
	sw (p+2, p+3);
	}

/*page*/
#ifndef GETONLY
/*==============================================================*/
/*	AutoPW		- Set PW table to auto mode		*/
/*==============================================================*/
AutoPW (set)
int	set;
{
struct PWTentry	*p;
int		i;

#ifndef NODEBUG
	printf ("\tPWT set to %s\n", set ? "Auto" : "Manual");
#endif
	InitPW (1);
	if (set && !AutoMode()) {
		PWT.autoflag |= 0x01;
		WritePWT ();
		}
	else if (!set && AutoMode()) {
		PWT.autoflag &= ~0x01;
		WritePWT ();
		}
	}

/*page*/
/*==============================================================*/
/*	ClrPW		- Clear PWtable				*/
/*==============================================================*/
int ClrPW ()
{
#ifndef NODEBUG
	printf ("\tClear PWT\n");
#endif
	if (!InitPW(1)) return FALSE;
	clear (&PWTable [1], (PWTMAX - 1) * sizeof (struct PWTentry), ' ');
	PWT.autoflag = 0;
	PWT.PWreserved = 0;
	WritePWT ();
	return TRUE;
	}
/*page*/

#ifndef NODEBUG
/*==============================================================*/
/*	DumpPW	- dump the password table			*/
/*==============================================================*/
DumpPW () {
struct PWTentry *p;
int		i;

	printf ("DUMP OF PASSWORD TABLE, autoflag = %0x\n", PWT.autoflag);
	if (PWTable != PWT.table)
		printf ("ERROR PWTable != PWT.table\n");
	for (p = PWTable, i = 0; i < PWTMAX; i++, p++)
		if (p->Sys_Password [0] == ' ') break;
		else printf ("\t%-6.6s\n", p->Sys_Password);
	printf ("END OF LIST\n");	
	}
#endif
#endif /* GETONLY */
/*page*/
/*==============================================================*/
/*	GetPW	- get and check a password			*/
/*==============================================================*/
#ifdef OVERLAY
int ovmain (level)
#else
int GetPW (level)
#endif
int	level;
{
CHAR	p [7];
CHAR	*q;
int	try;

#ifndef NODEBUG
	printf ("\tGetPW. level = %d,\n", level);
#endif
	if (!InitPW (level)) return FALSE;
	q = PWTable [level].Sys_Password;
	if (!IsPW (level))
		return TRUE;
	
	try = 3;
	while (try--) {
		if (!PWInput (p, PWLEN)) zabort ();
		krypt (p);
#ifndef NODEBUG
		printf ("\t\t%d. compare '%-6.6s' to '%-6.6s'\n",
			level, p, q);
#endif
		if (strncmp (p, q, PWLEN) == 0) {
#ifndef NODEBUG
			printf ("\t\tPassword matched\n");
#endif	
			return TRUE;
			}
		}
	zabort (); /* No match - tuff luck! */
	}

/*page*/
/*==============================================================*/
/*	IsPW	- returns true if a password exists for 'level'	*/
/*==============================================================*/
IsPW (level)
int	level;
{
	if (AutoMode () || strncmp (BlankPW, PWTable [level].Sys_Password, 
		PWLEN) == 0) {
#ifndef NODEBUG
		if (AutoMode ()) printf ("\t\tPassword AutoMode.\n");
		else printf ("\t\tPassword Blank.\n");
#endif
		return FALSE;
		}
	else return TRUE;
	}

/*page*/
/*==============================================================*/
/*	InitPWT	- read in PW table				*/
/*==============================================================*/
#ifdef HARDIO
#define USERNO	(*(CHAR *) 0x47)
#endif

int InitPW (level)
int	level;
{
#ifdef HARDIO
	if (!USERNO) {
		printf (NotMaster);
		zabort ();
		}
#endif
	if (level >= PWTMAX || level < 0) return FALSE;

	if (!PWTreadin) {
		getPWT (&PWT);
		PWTable = PWT.table;
#ifndef NODEBUG
		DumpPW ();
#endif
		PWTreadin = true;
		}
	return TRUE;
}

/*page*/
#ifndef GETONLY
/*==============================================================*/
/*	SetPW	- set a password				*/
/*==============================================================*/
int SetPW (level)
int	level;
{
CHAR	*oldp;
CHAR	*p;
CHAR	p1 [7];
CHAR	p2 [7];
int	i;

#ifndef NODEBUG
	printf ("\tSetPW. level = %d, ", level);
#endif
	if (!InitPW (level)) return FALSE;
	if (!PWInput (p1, PWLEN)) zabort ();
	printf (EnterAgain);
	if (!PWInput (p2, PWLEN)) zabort ();
	while (strncmp (p1, p2, PWLEN) != 0) {
		printf (NoGood);
		if (!PWInput (p1, PWLEN)) zabort ();
		printf (EnterAgain);
		if (!PWInput (p2, PWLEN)) zabort ();
		}

	p = p1; /* Bug in AZTEC C requires this */
	krypt (p);
	oldp = PWTable [level] . Sys_Password;

	for (i = 0; i < PWLEN; i++, p++, oldp++)
		*oldp = *p;
#ifndef NODEBUG
	printf ("\tPwt [%d] = %-6.6s\n", level, PWTable [level] . Sys_Password);
#endif
	WritePWT ();
	return TRUE;
	}
#endif /* GETONLY */

/*page*/
/*==============================================================*/
/*	SepBoot		- check to see if upgraded to seperated	*/
/*			  boot.					*/
/*==============================================================*/
int SepBoot () {

	InitPW (1);
	if (strncmp (SEPBOOT, PWTable [0].Sys_Password, PWLEN) == 0)
		return TRUE;
	else {
#ifndef NODEBUG
		printf ("\tSepBoot. PWTable [0] = %-6.6s\n",
			PWTable [0] . Sys_Password);
#endif
		return FALSE;
		}
	}

/*page*/
/*==============================================================*/
/*	WritePWT	- write out the password table		*/
/*==============================================================*/
WritePWT () {
	putPWT (&PWT);
	}
	
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/








