summaryrefslogblamecommitdiffstats
path: root/main/common/password.c
blob: 94f8f9c1abeb10effd305fd34c358c507998cf3b (plain) (tree)
































































































































































































































































































                                                                                          
/**************************************************************************
 *
 * Copyright (c) 2013 Alcatel-Lucent
 * 
 * Alcatel Lucent licenses this file to You under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License.  A copy of the License is contained the
 * file LICENSE at the top level of this repository.
 * You may also obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **************************************************************************
 *
 * password:
 *
 * Code that supports the use of a password in the monitor.
 *
 * Original author:     Ed Sutter (ed.sutter@alcatel-lucent.com)
 *
 */
#include "config.h"
#include "stddefs.h"
#include "genlib.h"
#include "ether.h"
#include "tfs.h"
#include "tfsprivate.h"

#if INCLUDE_USRLVL

extern	char *crypt(char *,char *,char *);

/* PASSWORD_FILE:
 *	The name of the file that is used to store passwords.
 */
#ifndef PASSWORD_FILE
#define PASSWORD_FILE	".monpswd"
#endif

#define SALT0	'T'
#define SALT1	'J'

int
passwordFileExists(void)
{
	if (tfsstat(PASSWORD_FILE))
		return(1);
	return(0);
}

/* backdoor():
 *	A mechanism that allows a password to be generated based on the
 *	MAC address of the board...
 *
 *	Return 1 if the password matches the return of crypt(KEY,SALT).
 *	Where:
 *		KEY is an 8-character string created from the MAC address
 *			stored in the ETHERADD environment variable;
 *		SALT is a 2-character string made up of the first and last
 *			character of the ETHERADD env var;
 */
int
backdoor(char *password)
{
	int		i;
	char	*etherstr, salt[3], encryption[32];
	unsigned char etherbin[9];

	etherstr = getenv("ETHERADD");	
	if (!etherstr)	/* just in case... */
		etherstr = "00:00:00:00:00:00";

	/* 2 salt characters are the first and last characters of etherstr: */
	salt[0] = etherstr[0];
	salt[1] = etherstr[strlen(etherstr)-1];
	salt[2] = 0;

	EtherToBin(etherstr,etherbin);
	etherbin[6] = 'A';
	etherbin[7] = 'a';
	etherbin[8] = 0;

	for(i=0;i<6;i++) {
		while (etherbin[i] > 0x7e) {
			etherbin[i] -= 0x20;
			etherbin[6]++;
		}
		while (etherbin[i] < 0x20) {
			etherbin[i] += 0x8;
			etherbin[7]++;
		}
	}
		
	crypt((char *)etherbin,salt,encryption);

	/* Note that the first two characters of the return from crypt() */
	/* are not used in the comparison... */
	if (!strcmp(password,encryption+2))
		return(1);
	else
		return(0);
}

/* validPassword():
 *	Called with a password and user level.	There are a few different ways
 *	in which this can pass...
 *	1. If there is no PASSWORD_FILE in TFS, return true.
 *	2. If the password matches the backdoor entry, return true.
 *	3. If the password matches appropriate entry in the password file,
 *	   return  true.
 */

int
validPassword(char *password, int ulvl)
{
	char	line[80];
	int		(*fptr)(void);
	int		tfd, lno, pass, lsize;

	/* If there is a password file, then use it.
	 * If there is no password file, then call extValidPassword() to
	 * support systems that store the password some other way.
	 * The extValidPassword() function should return 0 if password check
	 * failed, 1 if the check succeeded and -1 if there is no external
	 * password storage hardware.
	 * Finally, if there is no password file, AND there is no external
	 * password storage hardware, then just return 1 to
	 * indicate that ANY password is a valid password.  In other words...
	 * the password protection stuff is only enabled if you have a password
	 * stored away somewhere.
	 */
	if (!passwordFileExists()) {
		static	int warning;

		switch(extValidPassword(password,ulvl)) {
			case 0:			/* Password check failed. */
				return(0);
			case 1:			/* Password check passed. */
				return(1);
			default:		/* No external password check in use. */
				break;
		}
		if (!warning) {
			printf("WARNING: no %s file, security inactive.\n",PASSWORD_FILE);
			warning = 1;
		}
		return(1);
	}

	/* First check for backdoor entry... */
	if (backdoor(password))
		return(1);

	/* Incoming user level must be in valid range... */
	if ((ulvl < MINUSRLEVEL) || (ulvl > MAXUSRLEVEL))
		return(0);

	/* If user level is MINUSRLEVEL, there is no need for a password. */
	if (ulvl == MINUSRLEVEL)
		return(1);

	/* Check for a match in the password file...
	 * The PASSWORD_FILE dedicates one line for each user level.
	 * Line1 is password for user level 1.
	 * Line2 is password for user level 2.
	 * Line3 is password for user level 3.
	 * User level 0 doesn't require a password.
	 */

	/* Force the getUsrLvl() function to return MAX: */
	fptr = (int(*)(void))setTmpMaxUsrLvl();

	tfd = tfsopen(PASSWORD_FILE,TFS_RDONLY,0);
	if (tfd < 0) {
		/* Restore the original getUsrLvl() functionality: */
		clrTmpMaxUsrLvl(fptr);
		printf("%s\n",(char *)tfsctrl(TFS_ERRMSG,tfd,0));
		return(0);
	}

	lno = 1;
	pass = 0;
	while((lsize=tfsgetline(tfd,line,sizeof(line)))) {
		char	encryption[32], salt[3];

		if (lno != ulvl) {
			lno++;
			continue;
		}

		line[lsize-1] = 0;			/* Remove the newline */

		salt[0] = SALT0;
		salt[1] = SALT1;
		salt[2] = 0;

		crypt(password,salt,encryption);

		if (!strncmp(line,encryption+2,strlen(line)-2))
			pass = 1;
		break;
	}
	tfsclose(tfd,0);
	
	/* Restore the original getUsrLvl() functionality: */
	clrTmpMaxUsrLvl(fptr);

	return(pass);
}

/* newPasswordFile():
 *	Prompt the user for three passwords.  One for each user level.
 *	Then, after retrieving them, make sure the user wants to update
 *	the password file; if yes, do it; else abort.
 */
int
newPasswordFile(void)
{
	int		err, i;
	char	pswd1[16], pswd2[16];
	char	salt[3], *epwp, buf[32], epswd[34*3], flags[8];

	/* For each of the three levels (1,2&3), get the password, encrypt it
	 * and concatenate newline for storate into the password file.
	 */

	epwp = epswd;
	for(i=1;i<4;i++) {
		while(1) {
			printf("Lvl%d ",i);
			getpass("passwd: ",pswd1,sizeof(pswd1)-1,0);
			if (strlen(pswd1) < 8) {
				printf("password must be >= 8 chars.\n");
				continue;
			}
			getpass("verify: ",pswd2,sizeof(pswd2)-1,0);
			if (strcmp(pswd1,pswd2))
				printf("Entries do not match, try again...\n");
			else
				break;
		}
		salt[0] = SALT0;
		salt[1] = SALT1;
		salt[2] = 0;
		crypt(pswd1,salt,buf);
		sprintf(epwp,"%s\n",&buf[2]);
		epwp += strlen(epwp);
	}

	if (!askuser("Are you sure?"))
		return(0);

	err = tfsunlink(PASSWORD_FILE);
	if ((err != TFS_OKAY) && (err != TFSERR_NOFILE)) {
		printf("%s\n",(char *)tfsctrl(TFS_ERRMSG,err,0));
		return(-1);
	}

	sprintf(flags,"u%d",MAXUSRLEVEL);
	err = tfsadd(PASSWORD_FILE,0, flags, (uchar *)epswd, strlen(epswd));
	if (err != TFS_OKAY) {
		printf("%s\n",(char *)tfsctrl(TFS_ERRMSG,err,0));
		return(-1);
	}
	return(0);
}


#ifndef EXT_VALID_PASSWORD
/* extValidPassword():
 * See validPassword() above for notes on the purpose of this function.
 *
 * This is the default stub, if a real extValidPassword() function is
 * provided by the port, then EXT_VALID_PASSWORD should be defined in
 * that port's config.h file.
*/
int
extValidPassword(char *password, int ulvl)
{
	return(-1);
}
#endif	/* EXT_VALID_PASSWORD */
#endif	/* INCLUDE_USRLVL */